am 7da1ad69: am c524ca27: Merge "Fix NPE on some phones at startup." into jb-dev

* commit '7da1ad699989db8417ce54eb26697eae4a30f634':
  Fix NPE on some phones at startup.
diff --git a/Android.mk b/Android.mk
index b9157fe..5fb66ab 100644
--- a/Android.mk
+++ b/Android.mk
@@ -89,7 +89,13 @@
 	core/java/android/bluetooth/IBluetoothA2dp.aidl \
 	core/java/android/bluetooth/IBluetoothCallback.aidl \
 	core/java/android/bluetooth/IBluetoothHeadset.aidl \
+	core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \
+	core/java/android/bluetooth/IBluetoothHealth.aidl \
 	core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
+	core/java/android/bluetooth/IBluetoothInputDevice.aidl \
+	core/java/android/bluetooth/IBluetoothPan.aidl \
+	core/java/android/bluetooth/IBluetoothManager.aidl \
+	core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
 	core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
 	core/java/android/content/IClipboard.aidl \
@@ -143,6 +149,8 @@
 	core/java/android/view/accessibility/IAccessibilityManager.aidl \
 	core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
 	core/java/android/view/IApplicationToken.aidl \
+	core/java/android/view/IInputFilter.aidl \
+	core/java/android/view/IInputFilterHost.aidl \
 	core/java/android/view/IOnKeyguardExitResult.aidl \
 	core/java/android/view/IRotationWatcher.aidl \
 	core/java/android/view/IWindow.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0d8a7cd..61e5b4c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -133,6 +133,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClientCallback.P)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClient.P)
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
+$(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/16.txt b/api/16.txt
index bc97e81..85464ce 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -7324,7 +7324,6 @@
     method public void prepareForInsert();
     method public void prepareForReplace();
     method public long replace(android.content.ContentValues);
-    field public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4; // 0x4
   }
 
   public final class DefaultDatabaseErrorHandler implements android.database.DatabaseErrorHandler {
@@ -15991,7 +15990,7 @@
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
   }
 
-  public class PowerManager {
+  public final class PowerManager {
     method public void goToSleep(long);
     method public boolean isScreenOn();
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
@@ -16005,7 +16004,7 @@
     field public static final int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
   }
 
-  public class PowerManager.WakeLock {
+  public final class PowerManager.WakeLock {
     method public void acquire();
     method public void acquire(long);
     method public boolean isHeld();
diff --git a/api/current.txt b/api/current.txt
index 880170d..2716d5b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -72,6 +72,7 @@
     field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
     field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
     field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
+    field public static final java.lang.String NET_TUNNELING = "android.permission.NET_TUNNELING";
     field public static final java.lang.String NFC = "android.permission.NFC";
     field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
     field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
@@ -602,15 +603,20 @@
     field public static final int layerType = 16843604; // 0x1010354
     field public static final int layout = 16842994; // 0x10100f2
     field public static final int layoutAnimation = 16842988; // 0x10100ec
+    field public static final int layoutDirection = 16843698; // 0x10103b2
     field public static final int layout_above = 16843140; // 0x1010184
     field public static final int layout_alignBaseline = 16843142; // 0x1010186
     field public static final int layout_alignBottom = 16843146; // 0x101018a
+    field public static final int layout_alignEnd = 16843706; // 0x10103ba
     field public static final int layout_alignLeft = 16843143; // 0x1010187
     field public static final int layout_alignParentBottom = 16843150; // 0x101018e
+    field public static final int layout_alignParentEnd = 16843708; // 0x10103bc
     field public static final int layout_alignParentLeft = 16843147; // 0x101018b
     field public static final int layout_alignParentRight = 16843149; // 0x101018d
+    field public static final int layout_alignParentStart = 16843707; // 0x10103bb
     field public static final int layout_alignParentTop = 16843148; // 0x101018c
     field public static final int layout_alignRight = 16843145; // 0x1010189
+    field public static final int layout_alignStart = 16843705; // 0x10103b9
     field public static final int layout_alignTop = 16843144; // 0x1010188
     field public static final int layout_alignWithParentIfMissing = 16843154; // 0x1010192
     field public static final int layout_below = 16843141; // 0x1010185
@@ -623,15 +629,19 @@
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
     field public static final int layout_marginBottom = 16843002; // 0x10100fa
+    field public static final int layout_marginEnd = 16843702; // 0x10103b6
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
+    field public static final int layout_marginStart = 16843701; // 0x10103b5
     field public static final int layout_marginTop = 16843000; // 0x10100f8
     field public static final int layout_row = 16843643; // 0x101037b
     field public static final int layout_rowSpan = 16843644; // 0x101037c
     field public static final int layout_scale = 16843155; // 0x1010193
     field public static final int layout_span = 16843085; // 0x101014d
+    field public static final int layout_toEndOf = 16843704; // 0x10103b8
     field public static final int layout_toLeftOf = 16843138; // 0x1010182
     field public static final int layout_toRightOf = 16843139; // 0x1010183
+    field public static final int layout_toStartOf = 16843703; // 0x10103b7
     field public static final int layout_weight = 16843137; // 0x1010181
     field public static final int layout_width = 16842996; // 0x10100f4
     field public static final int layout_x = 16843135; // 0x101017f
@@ -650,8 +660,10 @@
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
     field public static final int listPreferredItemHeightLarge = 16843654; // 0x1010386
     field public static final int listPreferredItemHeightSmall = 16843655; // 0x1010387
+    field public static final int listPreferredItemPaddingEnd = 16843710; // 0x10103be
     field public static final int listPreferredItemPaddingLeft = 16843683; // 0x10103a3
     field public static final int listPreferredItemPaddingRight = 16843684; // 0x10103a4
+    field public static final int listPreferredItemPaddingStart = 16843709; // 0x10103bd
     field public static final int listSelector = 16843003; // 0x10100fb
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
@@ -722,8 +734,10 @@
     field public static final int packageNames = 16843649; // 0x1010381
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
+    field public static final int paddingEnd = 16843700; // 0x10103b4
     field public static final int paddingLeft = 16842966; // 0x10100d6
     field public static final int paddingRight = 16842968; // 0x10100d8
+    field public static final int paddingStart = 16843699; // 0x10103b3
     field public static final int paddingTop = 16842967; // 0x10100d7
     field public static final int panelBackground = 16842846; // 0x101005e
     field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -935,6 +949,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -965,6 +980,7 @@
     field public static final int tension = 16843370; // 0x101026a
     field public static final int testOnly = 16843378; // 0x1010272
     field public static final int text = 16843087; // 0x101014f
+    field public static final int textAlignment = 16843697; // 0x10103b1
     field public static final int textAllCaps = 16843660; // 0x101038c
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
@@ -1004,6 +1020,7 @@
     field public static final int textColorTertiary = 16843282; // 0x1010212
     field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
     field public static final int textCursorDrawable = 16843618; // 0x1010362
+    field public static final int textDirection = 16843696; // 0x10103b0
     field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -4333,6 +4350,7 @@
     method public void deleteHost();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
+    method protected void onProvidersChanged();
     method public void startListening();
     method public void stopListening();
   }
@@ -4429,6 +4447,7 @@
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+    method public void finalize();
     method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
     method public int getConnectionState(android.bluetooth.BluetoothDevice);
     method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
@@ -5805,7 +5824,9 @@
     field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
     field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+    field public static final java.lang.String EXTRA_ORIGINATING_URL = "android.intent.extra.ORIGINATING_URL";
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
     field public static final java.lang.String EXTRA_REPLACING = "android.intent.extra.REPLACING";
     field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
@@ -6262,6 +6283,7 @@
     field public static final int FLAG_STOPPED = 2097152; // 0x200000
     field public static final int FLAG_SUPPORTS_LARGE_SCREENS = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1024; // 0x400
+    field public static final int FLAG_SUPPORTS_RTL = 4194304; // 0x400000
     field public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 8192; // 0x2000
     field public static final int FLAG_SUPPORTS_SMALL_SCREENS = 512; // 0x200
     field public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 524288; // 0x80000
@@ -6942,7 +6964,7 @@
     method public int getIndexCount();
     method public int getInt(int, int);
     method public int getInteger(int, int);
-    method public int getLayoutDimension(int, java.lang.String);
+    method public deprecated int getLayoutDimension(int, java.lang.String);
     method public int getLayoutDimension(int, int);
     method public java.lang.String getNonResourceString(int);
     method public java.lang.String getPositionDescription();
@@ -7307,7 +7329,7 @@
     field public static final int STATEMENT_UPDATE = 2; // 0x2
   }
 
-  public static class DatabaseUtils.InsertHelper {
+  public static deprecated class DatabaseUtils.InsertHelper {
     ctor public DatabaseUtils.InsertHelper(android.database.sqlite.SQLiteDatabase, java.lang.String);
     method public void bind(int, double);
     method public void bind(int, float);
@@ -7324,7 +7346,6 @@
     method public void prepareForInsert();
     method public void prepareForReplace();
     method public long replace(android.content.ContentValues);
-    field public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4; // 0x4
   }
 
   public final class DefaultDatabaseErrorHandler implements android.database.DatabaseErrorHandler {
@@ -8110,6 +8131,7 @@
     method public final int getWidth();
     method public final boolean hasAlpha();
     method public final boolean isMutable();
+    method public final boolean isPremultiplied();
     method public final boolean isRecycled();
     method public void prepareToDraw();
     method public void recycle();
@@ -8599,6 +8621,7 @@
     method public android.graphics.Paint.Align getTextAlign();
     method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
     method public void getTextBounds(char[], int, int, android.graphics.Rect);
+    method public java.util.Locale getTextLocale();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
     method public float getTextScaleX();
@@ -8648,6 +8671,7 @@
     method public void setStyle(android.graphics.Paint.Style);
     method public void setSubpixelText(boolean);
     method public void setTextAlign(android.graphics.Paint.Align);
+    method public void setTextLocale(java.util.Locale);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSkewX(float);
@@ -9242,6 +9266,7 @@
     method public android.graphics.drawable.Drawable getCurrent();
     method public int getIntrinsicHeight();
     method public int getIntrinsicWidth();
+    method public int getLayoutDirection();
     method public final int getLevel();
     method public int getMinimumHeight();
     method public int getMinimumWidth();
@@ -9269,6 +9294,7 @@
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
     method public void setDither(boolean);
     method public void setFilterBitmap(boolean);
+    method public void setLayoutDirection(int);
     method public final boolean setLevel(int);
     method public boolean setState(int[]);
     method public boolean setVisible(boolean, boolean);
@@ -10486,6 +10512,7 @@
     method public float getAccuracy();
     method public double getAltitude();
     method public float getBearing();
+    method public long getElapsedRealtimeNano();
     method public android.os.Bundle getExtras();
     method public double getLatitude();
     method public double getLongitude();
@@ -10505,6 +10532,7 @@
     method public void setAccuracy(float);
     method public void setAltitude(double);
     method public void setBearing(float);
+    method public void setElapsedRealtimeNano(long);
     method public void setExtras(android.os.Bundle);
     method public void setLatitude(double);
     method public void setLongitude(double);
@@ -11375,6 +11403,7 @@
     field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
     field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
     field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
+    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
     field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
@@ -13747,6 +13776,174 @@
 
 package android.opengl {
 
+  public class EGL14 {
+    ctor public EGL14();
+    method public static boolean eglBindAPI(int);
+    method public static boolean eglBindTexImage(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static boolean eglChooseConfig(android.opengl.EGLDisplay, int[], int, android.opengl.EGLConfig[], int, int, int[], int);
+    method public static boolean eglCopyBuffers(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static android.opengl.EGLContext eglCreateContext(android.opengl.EGLDisplay, android.opengl.EGLConfig, android.opengl.EGLContext, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePbufferFromClientBuffer(android.opengl.EGLDisplay, int, int, android.opengl.EGLConfig, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePbufferSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int);
+    method public static android.opengl.EGLSurface eglCreateWindowSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.lang.Object, int[], int);
+    method public static boolean eglDestroyContext(android.opengl.EGLDisplay, android.opengl.EGLContext);
+    method public static boolean eglDestroySurface(android.opengl.EGLDisplay, android.opengl.EGLSurface);
+    method public static boolean eglGetConfigAttrib(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int);
+    method public static boolean eglGetConfigs(android.opengl.EGLDisplay, android.opengl.EGLConfig[], int, int, int[], int);
+    method public static android.opengl.EGLContext eglGetCurrentContext();
+    method public static android.opengl.EGLDisplay eglGetCurrentDisplay();
+    method public static android.opengl.EGLSurface eglGetCurrentSurface(int);
+    method public static android.opengl.EGLDisplay eglGetDisplay(int);
+    method public static int eglGetError();
+    method public static boolean eglInitialize(android.opengl.EGLDisplay, int[], int, int[], int);
+    method public static boolean eglMakeCurrent(android.opengl.EGLDisplay, android.opengl.EGLSurface, android.opengl.EGLSurface, android.opengl.EGLContext);
+    method public static int eglQueryAPI();
+    method public static boolean eglQueryContext(android.opengl.EGLDisplay, android.opengl.EGLContext, int, int[], int);
+    method public static java.lang.String eglQueryString(android.opengl.EGLDisplay, int);
+    method public static boolean eglQuerySurface(android.opengl.EGLDisplay, android.opengl.EGLSurface, int, int[], int);
+    method public static boolean eglReleaseTexImage(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static boolean eglReleaseThread();
+    method public static boolean eglSurfaceAttrib(android.opengl.EGLDisplay, android.opengl.EGLSurface, int, int);
+    method public static boolean eglSwapBuffers(android.opengl.EGLDisplay, android.opengl.EGLSurface);
+    method public static boolean eglSwapInterval(android.opengl.EGLDisplay, int);
+    method public static boolean eglTerminate(android.opengl.EGLDisplay);
+    method public static boolean eglWaitClient();
+    method public static boolean eglWaitGL();
+    method public static boolean eglWaitNative(int);
+    field public static final int EGL_ALPHA_MASK_SIZE = 12350; // 0x303e
+    field public static final int EGL_ALPHA_SIZE = 12321; // 0x3021
+    field public static final int EGL_BACK_BUFFER = 12420; // 0x3084
+    field public static final int EGL_BAD_ACCESS = 12290; // 0x3002
+    field public static final int EGL_BAD_ALLOC = 12291; // 0x3003
+    field public static final int EGL_BAD_ATTRIBUTE = 12292; // 0x3004
+    field public static final int EGL_BAD_CONFIG = 12293; // 0x3005
+    field public static final int EGL_BAD_CONTEXT = 12294; // 0x3006
+    field public static final int EGL_BAD_CURRENT_SURFACE = 12295; // 0x3007
+    field public static final int EGL_BAD_DISPLAY = 12296; // 0x3008
+    field public static final int EGL_BAD_MATCH = 12297; // 0x3009
+    field public static final int EGL_BAD_NATIVE_PIXMAP = 12298; // 0x300a
+    field public static final int EGL_BAD_NATIVE_WINDOW = 12299; // 0x300b
+    field public static final int EGL_BAD_PARAMETER = 12300; // 0x300c
+    field public static final int EGL_BAD_SURFACE = 12301; // 0x300d
+    field public static final int EGL_BIND_TO_TEXTURE_RGB = 12345; // 0x3039
+    field public static final int EGL_BIND_TO_TEXTURE_RGBA = 12346; // 0x303a
+    field public static final int EGL_BLUE_SIZE = 12322; // 0x3022
+    field public static final int EGL_BUFFER_DESTROYED = 12437; // 0x3095
+    field public static final int EGL_BUFFER_PRESERVED = 12436; // 0x3094
+    field public static final int EGL_BUFFER_SIZE = 12320; // 0x3020
+    field public static final int EGL_CLIENT_APIS = 12429; // 0x308d
+    field public static final int EGL_COLOR_BUFFER_TYPE = 12351; // 0x303f
+    field public static final int EGL_CONFIG_CAVEAT = 12327; // 0x3027
+    field public static final int EGL_CONFIG_ID = 12328; // 0x3028
+    field public static final int EGL_CONFORMANT = 12354; // 0x3042
+    field public static final int EGL_CONTEXT_CLIENT_TYPE = 12439; // 0x3097
+    field public static final int EGL_CONTEXT_CLIENT_VERSION = 12440; // 0x3098
+    field public static final int EGL_CONTEXT_LOST = 12302; // 0x300e
+    field public static final int EGL_CORE_NATIVE_ENGINE = 12379; // 0x305b
+    field public static final int EGL_DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int EGL_DEPTH_SIZE = 12325; // 0x3025
+    field public static final int EGL_DISPLAY_SCALING = 10000; // 0x2710
+    field public static final int EGL_DRAW = 12377; // 0x3059
+    field public static final int EGL_EXTENSIONS = 12373; // 0x3055
+    field public static final int EGL_FALSE = 0; // 0x0
+    field public static final int EGL_GREEN_SIZE = 12323; // 0x3023
+    field public static final int EGL_HEIGHT = 12374; // 0x3056
+    field public static final int EGL_HORIZONTAL_RESOLUTION = 12432; // 0x3090
+    field public static final int EGL_LARGEST_PBUFFER = 12376; // 0x3058
+    field public static final int EGL_LEVEL = 12329; // 0x3029
+    field public static final int EGL_LUMINANCE_BUFFER = 12431; // 0x308f
+    field public static final int EGL_LUMINANCE_SIZE = 12349; // 0x303d
+    field public static final int EGL_MATCH_NATIVE_PIXMAP = 12353; // 0x3041
+    field public static final int EGL_MAX_PBUFFER_HEIGHT = 12330; // 0x302a
+    field public static final int EGL_MAX_PBUFFER_PIXELS = 12331; // 0x302b
+    field public static final int EGL_MAX_PBUFFER_WIDTH = 12332; // 0x302c
+    field public static final int EGL_MAX_SWAP_INTERVAL = 12348; // 0x303c
+    field public static final int EGL_MIN_SWAP_INTERVAL = 12347; // 0x303b
+    field public static final int EGL_MIPMAP_LEVEL = 12419; // 0x3083
+    field public static final int EGL_MIPMAP_TEXTURE = 12418; // 0x3082
+    field public static final int EGL_MULTISAMPLE_RESOLVE = 12441; // 0x3099
+    field public static final int EGL_MULTISAMPLE_RESOLVE_BOX = 12443; // 0x309b
+    field public static final int EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 512; // 0x200
+    field public static final int EGL_MULTISAMPLE_RESOLVE_DEFAULT = 12442; // 0x309a
+    field public static final int EGL_NATIVE_RENDERABLE = 12333; // 0x302d
+    field public static final int EGL_NATIVE_VISUAL_ID = 12334; // 0x302e
+    field public static final int EGL_NATIVE_VISUAL_TYPE = 12335; // 0x302f
+    field public static final int EGL_NONE = 12344; // 0x3038
+    field public static final int EGL_NON_CONFORMANT_CONFIG = 12369; // 0x3051
+    field public static final int EGL_NOT_INITIALIZED = 12289; // 0x3001
+    field public static android.opengl.EGLContext EGL_NO_CONTEXT;
+    field public static android.opengl.EGLDisplay EGL_NO_DISPLAY;
+    field public static android.opengl.EGLSurface EGL_NO_SURFACE;
+    field public static final int EGL_NO_TEXTURE = 12380; // 0x305c
+    field public static final int EGL_OPENGL_API = 12450; // 0x30a2
+    field public static final int EGL_OPENGL_BIT = 8; // 0x8
+    field public static final int EGL_OPENGL_ES2_BIT = 4; // 0x4
+    field public static final int EGL_OPENGL_ES_API = 12448; // 0x30a0
+    field public static final int EGL_OPENGL_ES_BIT = 1; // 0x1
+    field public static final int EGL_OPENVG_API = 12449; // 0x30a1
+    field public static final int EGL_OPENVG_BIT = 2; // 0x2
+    field public static final int EGL_OPENVG_IMAGE = 12438; // 0x3096
+    field public static final int EGL_PBUFFER_BIT = 1; // 0x1
+    field public static final int EGL_PIXEL_ASPECT_RATIO = 12434; // 0x3092
+    field public static final int EGL_PIXMAP_BIT = 2; // 0x2
+    field public static final int EGL_READ = 12378; // 0x305a
+    field public static final int EGL_RED_SIZE = 12324; // 0x3024
+    field public static final int EGL_RENDERABLE_TYPE = 12352; // 0x3040
+    field public static final int EGL_RENDER_BUFFER = 12422; // 0x3086
+    field public static final int EGL_RGB_BUFFER = 12430; // 0x308e
+    field public static final int EGL_SAMPLES = 12337; // 0x3031
+    field public static final int EGL_SAMPLE_BUFFERS = 12338; // 0x3032
+    field public static final int EGL_SINGLE_BUFFER = 12421; // 0x3085
+    field public static final int EGL_SLOW_CONFIG = 12368; // 0x3050
+    field public static final int EGL_STENCIL_SIZE = 12326; // 0x3026
+    field public static final int EGL_SUCCESS = 12288; // 0x3000
+    field public static final int EGL_SURFACE_TYPE = 12339; // 0x3033
+    field public static final int EGL_SWAP_BEHAVIOR = 12435; // 0x3093
+    field public static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 1024; // 0x400
+    field public static final int EGL_TEXTURE_2D = 12383; // 0x305f
+    field public static final int EGL_TEXTURE_FORMAT = 12416; // 0x3080
+    field public static final int EGL_TEXTURE_RGB = 12381; // 0x305d
+    field public static final int EGL_TEXTURE_RGBA = 12382; // 0x305e
+    field public static final int EGL_TEXTURE_TARGET = 12417; // 0x3081
+    field public static final int EGL_TRANSPARENT_BLUE_VALUE = 12341; // 0x3035
+    field public static final int EGL_TRANSPARENT_GREEN_VALUE = 12342; // 0x3036
+    field public static final int EGL_TRANSPARENT_RED_VALUE = 12343; // 0x3037
+    field public static final int EGL_TRANSPARENT_RGB = 12370; // 0x3052
+    field public static final int EGL_TRANSPARENT_TYPE = 12340; // 0x3034
+    field public static final int EGL_TRUE = 1; // 0x1
+    field public static final int EGL_VENDOR = 12371; // 0x3053
+    field public static final int EGL_VERSION = 12372; // 0x3054
+    field public static final int EGL_VERTICAL_RESOLUTION = 12433; // 0x3091
+    field public static final int EGL_VG_ALPHA_FORMAT = 12424; // 0x3088
+    field public static final int EGL_VG_ALPHA_FORMAT_NONPRE = 12427; // 0x308b
+    field public static final int EGL_VG_ALPHA_FORMAT_PRE = 12428; // 0x308c
+    field public static final int EGL_VG_ALPHA_FORMAT_PRE_BIT = 64; // 0x40
+    field public static final int EGL_VG_COLORSPACE = 12423; // 0x3087
+    field public static final int EGL_VG_COLORSPACE_LINEAR = 12426; // 0x308a
+    field public static final int EGL_VG_COLORSPACE_LINEAR_BIT = 32; // 0x20
+    field public static final int EGL_VG_COLORSPACE_sRGB = 12425; // 0x3089
+    field public static final int EGL_WIDTH = 12375; // 0x3057
+    field public static final int EGL_WINDOW_BIT = 4; // 0x4
+  }
+
+  public class EGLConfig extends android.opengl.EGLObjectHandle {
+  }
+
+  public class EGLContext extends android.opengl.EGLObjectHandle {
+  }
+
+  public class EGLDisplay extends android.opengl.EGLObjectHandle {
+  }
+
+  public abstract class EGLObjectHandle {
+    ctor protected EGLObjectHandle(int);
+    method public int getHandle();
+  }
+
+  public class EGLSurface extends android.opengl.EGLObjectHandle {
+  }
+
   public class ETC1 {
     ctor public ETC1();
     method public static void decodeBlock(java.nio.Buffer, java.nio.Buffer);
@@ -14654,8 +14851,12 @@
     method public static void glGenerateMipmap(int);
     method public static void glGetActiveAttrib(int, int, int, int[], int, int[], int, int[], int, byte[], int);
     method public static void glGetActiveAttrib(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetActiveAttrib(int, int, int[], int, int[], int);
+    method public static java.lang.String glGetActiveAttrib(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetActiveUniform(int, int, int, int[], int, int[], int, int[], int, byte[], int);
     method public static void glGetActiveUniform(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetActiveUniform(int, int, int[], int, int[], int);
+    method public static java.lang.String glGetActiveUniform(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetAttachedShaders(int, int, int[], int, int[], int);
     method public static void glGetAttachedShaders(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetAttribLocation(int, java.lang.String);
@@ -14680,6 +14881,7 @@
     method public static void glGetShaderPrecisionFormat(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetShaderSource(int, int, int[], int, byte[], int);
     method public static void glGetShaderSource(int, int, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetShaderSource(int);
     method public static void glGetShaderiv(int, int, int[], int);
     method public static void glGetShaderiv(int, int, java.nio.IntBuffer);
     method public static java.lang.String glGetString(int);
@@ -15991,7 +16193,7 @@
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
   }
 
-  public class PowerManager {
+  public final class PowerManager {
     method public void goToSleep(long);
     method public boolean isScreenOn();
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
@@ -16005,7 +16207,7 @@
     field public static final int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
   }
 
-  public class PowerManager.WakeLock {
+  public final class PowerManager.WakeLock {
     method public void acquire();
     method public void acquire(long);
     method public boolean isHeld();
@@ -16156,6 +16358,7 @@
   public final class SystemClock {
     method public static long currentThreadTimeMillis();
     method public static long elapsedRealtime();
+    method public static long elapsedRealtimeNano();
     method public static boolean setCurrentTimeMillis(long);
     method public static void sleep(long);
     method public static long uptimeMillis();
@@ -22491,6 +22694,10 @@
     method public android.util.JsonWriter value(java.lang.Number) throws java.io.IOException;
   }
 
+  public class LocaleUtil {
+    method public static int getLayoutDirectionFromLocale(java.util.Locale);
+  }
+
   public final class Log {
     method public static int d(java.lang.String, java.lang.String);
     method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
@@ -22633,6 +22840,17 @@
     method public void set(T, V);
   }
 
+  public class PropertyValueModel extends android.util.ValueModel {
+    method public T get();
+    method public H getHost();
+    method public android.util.Property<H, T> getProperty();
+    method public java.lang.Class<T> getType();
+    method public static android.util.PropertyValueModel<H, T> of(H, android.util.Property<H, T>);
+    method public static android.util.PropertyValueModel<H, T> of(H, java.lang.Class<T>, java.lang.String);
+    method public static android.util.PropertyValueModel of(java.lang.Object, java.lang.String);
+    method public void set(T);
+  }
+
   public class SparseArray implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
@@ -22781,6 +22999,14 @@
     field public int type;
   }
 
+  public abstract class ValueModel {
+    ctor protected ValueModel();
+    method public abstract T get();
+    method public abstract java.lang.Class<T> getType();
+    method public abstract void set(T);
+    field public static final android.util.ValueModel EMPTY;
+  }
+
   public class Xml {
     method public static android.util.AttributeSet asAttributeSet(org.xmlpull.v1.XmlPullParser);
     method public static android.util.Xml.Encoding findEncodingByName(java.lang.String) throws java.io.UnsupportedEncodingException;
@@ -22978,8 +23204,12 @@
   public class Gravity {
     ctor public Gravity();
     method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect);
+    method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect, int);
     method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect);
+    method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect, int);
     method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect);
+    method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect, int);
+    method public static int getAbsoluteGravity(int, int);
     method public static boolean isHorizontal(int);
     method public static boolean isVertical(int);
     field public static final int AXIS_CLIP = 8; // 0x8
@@ -24023,6 +24253,9 @@
     method public void buildDrawingCache(boolean);
     method public void buildLayer();
     method public boolean callOnClick();
+    method public boolean canResolveLayoutDirection();
+    method public boolean canResolveTextAlignment();
+    method public boolean canResolveTextDirection();
     method public boolean canScrollHorizontally(int);
     method public boolean canScrollVertically(int);
     method public void cancelLongPress();
@@ -24074,6 +24307,7 @@
     method protected boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
     method public void forceLayout();
+    method public static int generateViewId();
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
@@ -24112,6 +24346,7 @@
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLayerType();
+    method public int getLayoutDirection();
     method public android.view.ViewGroup.LayoutParams getLayoutParams();
     method public final int getLeft();
     method protected float getLeftFadingEdgeStrength();
@@ -24135,13 +24370,18 @@
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public int getOverScrollMode();
     method public int getPaddingBottom();
+    method public int getPaddingEnd();
     method public int getPaddingLeft();
     method public int getPaddingRight();
+    method public int getPaddingStart();
     method public int getPaddingTop();
     method public final android.view.ViewParent getParent();
     method public android.view.ViewParent getParentForAccessibility();
     method public float getPivotX();
     method public float getPivotY();
+    method public int getResolvedLayoutDirection();
+    method public int getResolvedTextAlignment();
+    method public int getResolvedTextDirection();
     method public android.content.res.Resources getResources();
     method public final int getRight();
     method protected float getRightFadingEdgeStrength();
@@ -24164,6 +24404,8 @@
     method public int getSystemUiVisibility();
     method public java.lang.Object getTag();
     method public java.lang.Object getTag(int);
+    method public int getTextAlignment();
+    method public int getTextDirection();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -24213,10 +24455,13 @@
     method public boolean isHovered();
     method public boolean isInEditMode();
     method public boolean isInTouchMode();
+    method protected static boolean isLayoutDirectionRtl(java.util.Locale);
     method public boolean isLayoutRequested();
+    method public boolean isLayoutRtl();
     method public boolean isLongClickable();
     method public boolean isOpaque();
     method protected boolean isPaddingOffsetRequired();
+    method public boolean isPaddingRelative();
     method public boolean isPressed();
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
@@ -24264,7 +24509,15 @@
     method protected void onLayout(boolean, int, int, int, int);
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
+    method public void onPaddingChanged(int);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void onResolveDrawables(int);
+    method public void onResolvedLayoutDirectionChanged();
+    method public void onResolvedLayoutDirectionReset();
+    method public void onResolvedTextAlignmentChanged();
+    method public void onResolvedTextAlignmentReset();
+    method public void onResolvedTextDirectionChanged();
+    method public void onResolvedTextDirectionReset();
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method protected android.os.Parcelable onSaveInstanceState();
     method public void onScreenStateChanged(int);
@@ -24307,8 +24560,16 @@
     method public void requestLayout();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+    method public void resetResolvedLayoutDirection();
+    method public void resetResolvedTextAlignment();
+    method public void resetResolvedTextDirection();
+    method public void resolveDrawables();
+    method public void resolveLayoutDirection();
+    method public void resolvePadding();
     method public static int resolveSize(int, int);
     method public static int resolveSizeAndState(int, int, int);
+    method public void resolveTextAlignment();
+    method public void resolveTextDirection();
     method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
     method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
     method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -24347,6 +24608,7 @@
     method public void setImportantForAccessibility(int);
     method public void setKeepScreenOn(boolean);
     method public void setLayerType(int, android.graphics.Paint);
+    method public void setLayoutDirection(int);
     method public void setLayoutParams(android.view.ViewGroup.LayoutParams);
     method public final void setLeft(int);
     method public void setLongClickable(boolean);
@@ -24370,6 +24632,7 @@
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOverScrollMode(int);
     method public void setPadding(int, int, int, int);
+    method public void setPaddingRelative(int, int, int, int);
     method public void setPivotX(float);
     method public void setPivotY(float);
     method public void setPressed(boolean);
@@ -24394,6 +24657,8 @@
     method public void setSystemUiVisibility(int);
     method public void setTag(java.lang.Object);
     method public void setTag(int, java.lang.Object);
+    method public void setTextAlignment(int);
+    method public void setTextDirection(int);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public void setTranslationX(float);
@@ -24452,6 +24717,10 @@
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
     field public static final int LAYER_TYPE_NONE = 0; // 0x0
     field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
+    field public static final int LAYOUT_DIRECTION_INHERIT = 2; // 0x2
+    field public static final int LAYOUT_DIRECTION_LOCALE = 3; // 0x3
+    field public static final int LAYOUT_DIRECTION_LTR = 0; // 0x0
+    field public static final int LAYOUT_DIRECTION_RTL = 1; // 0x1
     field public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; // 0x10
     field public static final int MEASURED_SIZE_MASK = 16777215; // 0xffffff
     field public static final int MEASURED_STATE_MASK = -16777216; // 0xff000000
@@ -24502,8 +24771,22 @@
     field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
+    field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
+    field protected static int TEXT_ALIGNMENT_DEFAULT;
+    field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
     field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
     field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
+    field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
+    field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
+    field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
+    field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
+    field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
+    field protected static int TEXT_DIRECTION_DEFAULT;
+    field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
+    field public static final int TEXT_DIRECTION_INHERIT = 0; // 0x0
+    field public static final int TEXT_DIRECTION_LOCALE = 5; // 0x5
+    field public static final int TEXT_DIRECTION_LTR = 3; // 0x3
+    field public static final int TEXT_DIRECTION_RTL = 4; // 0x4
     field public static final android.util.Property TRANSLATION_X;
     field public static final android.util.Property TRANSLATION_Y;
     field protected static final java.lang.String VIEW_LOG_TAG = "View";
@@ -24807,6 +25090,7 @@
     ctor public ViewGroup.LayoutParams(android.content.Context, android.util.AttributeSet);
     ctor public ViewGroup.LayoutParams(int, int);
     ctor public ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams);
+    method public void onResolveLayoutDirection(int);
     method protected void setBaseAttributes(android.content.res.TypedArray, int, int);
     field public static final deprecated int FILL_PARENT = -1; // 0xffffffff
     field public static final int MATCH_PARENT = -1; // 0xffffffff
@@ -24821,10 +25105,18 @@
     ctor public ViewGroup.MarginLayoutParams(int, int);
     ctor public ViewGroup.MarginLayoutParams(android.view.ViewGroup.MarginLayoutParams);
     ctor public ViewGroup.MarginLayoutParams(android.view.ViewGroup.LayoutParams);
+    method public int getLayoutDirection();
+    method public int getMarginEnd();
+    method public int getMarginStart();
+    method protected boolean isLayoutRtl();
+    method public boolean isMarginRelative();
+    method public void setLayoutDirection(int);
     method public void setMargins(int, int, int, int);
     field public int bottomMargin;
+    field public int endMargin;
     field public int leftMargin;
     field public int rightMargin;
+    field public int startMargin;
     field public int topMargin;
   }
 
@@ -25128,7 +25420,7 @@
     field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
     field public static final int FLAG_DIM_BEHIND = 2; // 0x2
     field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
-    field public static final int FLAG_DITHER = 4096; // 0x1000
+    field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
     field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
     field public static final int FLAG_FULLSCREEN = 1024; // 0x400
     field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000
@@ -26285,7 +26577,7 @@
     method public boolean onJsBeforeUnload(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
     method public boolean onJsConfirm(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
     method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult);
-    method public boolean onJsTimeout();
+    method public deprecated boolean onJsTimeout();
     method public void onProgressChanged(android.webkit.WebView, int);
     method public void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
     method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap);
@@ -26359,6 +26651,7 @@
     method public boolean getLightTouchEnabled();
     method public boolean getLoadWithOverviewMode();
     method public synchronized boolean getLoadsImagesAutomatically();
+    method public boolean getMediaPlaybackRequiresUserGesture();
     method public synchronized int getMinimumFontSize();
     method public synchronized int getMinimumLogicalFontSize();
     method public deprecated boolean getNavDump();
@@ -26408,6 +26701,7 @@
     method public void setLightTouchEnabled(boolean);
     method public void setLoadWithOverviewMode(boolean);
     method public synchronized void setLoadsImagesAutomatically(boolean);
+    method public void setMediaPlaybackRequiresUserGesture(boolean);
     method public synchronized void setMinimumFontSize(int);
     method public synchronized void setMinimumLogicalFontSize(int);
     method public deprecated void setNavDump(boolean);
@@ -27137,10 +27431,12 @@
     method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int);
   }
 
-  public class CheckBox extends android.widget.CompoundButton {
+  public class CheckBox extends android.widget.CompoundButton implements android.widget.ValueEditor {
     ctor public CheckBox(android.content.Context);
     ctor public CheckBox(android.content.Context, android.util.AttributeSet);
     ctor public CheckBox(android.content.Context, android.util.AttributeSet, int);
+    method public android.util.ValueModel<java.lang.Boolean> getValueModel();
+    method public void setValueModel(android.util.ValueModel<java.lang.Boolean>);
   }
 
   public abstract interface Checkable {
@@ -27155,7 +27451,6 @@
     ctor public CheckedTextView(android.content.Context, android.util.AttributeSet, int);
     method public android.graphics.drawable.Drawable getCheckMarkDrawable();
     method public boolean isChecked();
-    method public void onPaddingChanged(int);
     method public void setCheckMarkDrawable(int);
     method public void setCheckMarkDrawable(android.graphics.drawable.Drawable);
     method public void setChecked(boolean);
@@ -27298,7 +27593,7 @@
     field public static final int LETTERS_ONLY = 5; // 0x5
   }
 
-  public class DigitalClock extends android.widget.TextView {
+  public deprecated class DigitalClock extends android.widget.TextView {
     ctor public DigitalClock(android.content.Context);
     ctor public DigitalClock(android.content.Context, android.util.AttributeSet);
   }
@@ -27314,14 +27609,16 @@
     method public void setSize(int, int);
   }
 
-  public class EditText extends android.widget.TextView {
+  public class EditText extends android.widget.TextView implements android.widget.ValueEditor {
     ctor public EditText(android.content.Context);
     ctor public EditText(android.content.Context, android.util.AttributeSet);
     ctor public EditText(android.content.Context, android.util.AttributeSet, int);
     method public void extendSelection(int);
+    method public android.util.ValueModel<java.lang.CharSequence> getValueModel();
     method public void selectAll();
     method public void setSelection(int, int);
     method public void setSelection(int);
+    method public void setValueModel(android.util.ValueModel<java.lang.CharSequence>);
   }
 
   public abstract interface ExpandableListAdapter {
@@ -28114,19 +28411,25 @@
     field public static final int ABOVE = 2; // 0x2
     field public static final int ALIGN_BASELINE = 4; // 0x4
     field public static final int ALIGN_BOTTOM = 8; // 0x8
+    field public static final int ALIGN_END = 19; // 0x13
     field public static final int ALIGN_LEFT = 5; // 0x5
     field public static final int ALIGN_PARENT_BOTTOM = 12; // 0xc
+    field public static final int ALIGN_PARENT_END = 21; // 0x15
     field public static final int ALIGN_PARENT_LEFT = 9; // 0x9
     field public static final int ALIGN_PARENT_RIGHT = 11; // 0xb
+    field public static final int ALIGN_PARENT_START = 20; // 0x14
     field public static final int ALIGN_PARENT_TOP = 10; // 0xa
     field public static final int ALIGN_RIGHT = 7; // 0x7
+    field public static final int ALIGN_START = 18; // 0x12
     field public static final int ALIGN_TOP = 6; // 0x6
     field public static final int BELOW = 3; // 0x3
     field public static final int CENTER_HORIZONTAL = 14; // 0xe
     field public static final int CENTER_IN_PARENT = 13; // 0xd
     field public static final int CENTER_VERTICAL = 15; // 0xf
+    field public static final int END_OF = 17; // 0x11
     field public static final int LEFT_OF = 0; // 0x0
     field public static final int RIGHT_OF = 1; // 0x1
+    field public static final int START_OF = 16; // 0x10
     field public static final int TRUE = -1; // 0xffffffff
   }
 
@@ -28338,11 +28641,13 @@
     method public abstract java.lang.Object[] getSections();
   }
 
-  public class SeekBar extends android.widget.AbsSeekBar {
+  public class SeekBar extends android.widget.AbsSeekBar implements android.widget.ValueEditor {
     ctor public SeekBar(android.content.Context);
     ctor public SeekBar(android.content.Context, android.util.AttributeSet);
     ctor public SeekBar(android.content.Context, android.util.AttributeSet, int);
+    method public android.util.ValueModel<java.lang.Integer> getValueModel();
     method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
+    method public void setValueModel(android.util.ValueModel<java.lang.Integer>);
   }
 
   public static abstract interface SeekBar.OnSeekBarChangeListener {
@@ -28440,7 +28745,7 @@
     method public android.view.View newGroupView(boolean, android.view.ViewGroup);
   }
 
-  public class SlidingDrawer extends android.view.ViewGroup {
+  public deprecated class SlidingDrawer extends android.view.ViewGroup {
     ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet);
     ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet, int);
     method public void animateClose();
@@ -28667,9 +28972,12 @@
     method public final int getAutoLinkMask();
     method public int getCompoundDrawablePadding();
     method public android.graphics.drawable.Drawable[] getCompoundDrawables();
+    method public android.graphics.drawable.Drawable[] getCompoundDrawablesRelative();
     method public int getCompoundPaddingBottom();
+    method public int getCompoundPaddingEnd();
     method public int getCompoundPaddingLeft();
     method public int getCompoundPaddingRight();
+    method public int getCompoundPaddingStart();
     method public int getCompoundPaddingTop();
     method public final int getCurrentHintTextColor();
     method public final int getCurrentTextColor();
@@ -28729,8 +29037,10 @@
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
+    method public int getTotalPaddingEnd();
     method public int getTotalPaddingLeft();
     method public int getTotalPaddingRight();
+    method public int getTotalPaddingStart();
     method public int getTotalPaddingTop();
     method public final android.text.method.TransformationMethod getTransformationMethod();
     method public android.graphics.Typeface getTypeface();
@@ -28756,11 +29066,13 @@
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
     method protected void resetResolvedDrawables();
-    method protected void resolveDrawables();
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelative(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public void setCompoundDrawablesWithIntrinsicBounds(int, int, int, int);
     method public void setCompoundDrawablesWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public void setCursorVisible(boolean);
@@ -28804,7 +29116,6 @@
     method public void setMinWidth(int);
     method public final void setMovementMethod(android.text.method.MovementMethod);
     method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener);
-    method public void setPaddingRelative(int, int, int, int);
     method public void setPaintFlags(int);
     method public void setPrivateImeOptions(java.lang.String);
     method public void setRawInputType(int);
@@ -28900,7 +29211,7 @@
     method public void setTextOn(java.lang.CharSequence);
   }
 
-  public class TwoLineListItem extends android.widget.RelativeLayout {
+  public deprecated class TwoLineListItem extends android.widget.RelativeLayout {
     ctor public TwoLineListItem(android.content.Context);
     ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet);
     ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet, int);
@@ -28908,6 +29219,11 @@
     method public android.widget.TextView getText2();
   }
 
+  public abstract interface ValueEditor {
+    method public abstract android.util.ValueModel<T> getValueModel();
+    method public abstract void setValueModel(android.util.ValueModel<T>);
+  }
+
   public class VideoView extends android.view.SurfaceView implements android.widget.MediaController.MediaPlayerControl {
     ctor public VideoView(android.content.Context);
     ctor public VideoView(android.content.Context, android.util.AttributeSet);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 8b11d02..5878619 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -26,6 +26,7 @@
 dir_rec_t android_asec_dir;
 dir_rec_t android_app_dir;
 dir_rec_t android_app_private_dir;
+dir_rec_t android_media_dir;
 dir_rec_array_t android_system_dirs;
 
 int install(const char *pkgname, uid_t uid, gid_t gid)
@@ -273,17 +274,6 @@
     return delete_dir_contents(cachedir, 0, 0);
 }
 
-static int64_t disk_free()
-{
-    struct statfs sfs;
-    if (statfs(android_data_dir.path, &sfs) == 0) {
-        return sfs.f_bavail * sfs.f_bsize;
-    } else {
-        ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
-        return -1;
-    }
-}
-
 /* Try to ensure free_size bytes of storage are available.
  * Returns 0 on success.
  * This is rather simple-minded because doing a full LRU would
@@ -293,57 +283,66 @@
  */
 int free_cache(int64_t free_size)
 {
-    const char *name;
-    int dfd, subfd;
+    cache_t* cache;
+    int64_t avail;
     DIR *d;
     struct dirent *de;
-    int64_t avail;
-    char datadir[PKG_PATH_MAX];
+    char tmpdir[PATH_MAX];
+    char *dirpos;
 
-    avail = disk_free();
+    avail = data_disk_free();
     if (avail < 0) return -1;
 
     ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
     if (avail >= free_size) return 0;
 
-    if (create_persona_path(datadir, 0)) {
-        ALOGE("couldn't get directory for persona 0");
-        return -1;
+    cache = start_cache_collection();
+
+    // Collect cache files for primary user.
+    if (create_persona_path(tmpdir, 0) == 0) {
+        //ALOGI("adding cache files from %s\n", tmpdir);
+        add_cache_files(cache, tmpdir, "cache");
     }
 
-    d = opendir(datadir);
-    if (d == NULL) {
-        ALOGE("cannot open %s: %s\n", datadir, strerror(errno));
-        return -1;
-    }
-    dfd = dirfd(d);
-
-    while ((de = readdir(d))) {
-        if (de->d_type != DT_DIR) continue;
-        name = de->d_name;
-
-        /* always skip "." and ".." */
-        if (name[0] == '.') {
-            if (name[1] == 0) continue;
-            if ((name[1] == '.') && (name[2] == 0)) continue;
+    // Search for other users and add any cache files from them.
+    snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path,
+            SECONDARY_USER_PREFIX);
+    dirpos = tmpdir + strlen(tmpdir);
+    d = opendir(tmpdir);
+    if (d != NULL) {
+        while ((de = readdir(d))) {
+            if (de->d_type == DT_DIR) {
+                const char *name = de->d_name;
+                    /* always skip "." and ".." */
+                if (name[0] == '.') {
+                    if (name[1] == 0) continue;
+                    if ((name[1] == '.') && (name[2] == 0)) continue;
+                }
+                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
+                    strcpy(dirpos, name);
+                    //ALOGI("adding cache files from %s\n", tmpdir);
+                    add_cache_files(cache, tmpdir, "cache");
+                } else {
+                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
+                }
+            }
         }
-
-        subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-        if (subfd < 0) continue;
-
-        delete_dir_contents_fd(subfd, "cache");
-        close(subfd);
-
-        avail = disk_free();
-        if (avail >= free_size) {
-            closedir(d);
-            return 0;
-        }
+        closedir(d);
     }
-    closedir(d);
 
-    /* Fail case - not possible to free space */
-    return -1;
+    // Collect cache files on external storage (if it is mounted as part
+    // of the internal storage).
+    strcpy(tmpdir, android_media_dir.path);
+    if (lookup_media_dir(tmpdir, "Android") == 0
+            && lookup_media_dir(tmpdir, "data") == 0) {
+        //ALOGI("adding cache files from %s\n", tmpdir);
+        add_cache_files(cache, tmpdir, "cache");
+    }
+
+    clear_cache_files(cache, free_size);
+    finish_cache_collection(cache);
+
+    return data_disk_free() >= free_size ? 0 : -1;
 }
 
 int move_dex(const char *src, const char *dst)
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index fa4b8a6..89c059e 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -297,6 +297,11 @@
         return -1;
     }
 
+    // Get the android media directory.
+    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
+        return -1;
+    }
+
     // Take note of the system and vendor directories.
     android_system_dirs.count = 2;
 
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 1b843fd..f5853ff 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -60,6 +60,8 @@
 
 #define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA
 
+#define MEDIA_SUBDIR           "media/" // sub-directory under ANDROID_DATA
+
 /* other handy constants */
 
 #define PRIVATE_APP_SUBDIR     "app-private/" // sub-directory under ANDROID_DATA
@@ -91,8 +93,36 @@
 extern dir_rec_t android_app_private_dir;
 extern dir_rec_t android_data_dir;
 extern dir_rec_t android_asec_dir;
+extern dir_rec_t android_media_dir;
 extern dir_rec_array_t android_system_dirs;
 
+typedef struct cache_dir_struct {
+    struct cache_dir_struct* parent;
+    int32_t childCount;
+    int32_t hiddenCount;
+    int32_t deleted;
+    char name[];
+} cache_dir_t;
+
+typedef struct {
+    cache_dir_t* dir;
+    time_t modTime;
+    char name[];
+} cache_file_t;
+
+typedef struct {
+    size_t numDirs;
+    size_t availDirs;
+    cache_dir_t** dirs;
+    size_t numFiles;
+    size_t availFiles;
+    cache_file_t** files;
+    size_t numCollected;
+    void* memBlocks;
+    int8_t* curMemBlockAvail;
+    int8_t* curMemBlockEnd;
+} cache_t;
+
 /* util.c */
 
 int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
@@ -123,6 +153,18 @@
 
 int delete_dir_contents_fd(int dfd, const char *name);
 
+int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
+
+int64_t data_disk_free();
+
+cache_t* start_cache_collection();
+
+void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
+
+void clear_cache_files(cache_t* cache, int64_t free_size);
+
+void finish_cache_collection(cache_t* cache);
+
 int validate_system_app_path(const char* path);
 
 int get_path_from_env(dir_rec_t* rec, const char* var);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 52ec9e8..79db972 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -16,6 +16,8 @@
 
 #include "installd.h"
 
+#define CACHE_NOISY(x) //x
+
 int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
                                 const dir_rec_t* dir,
                                 const char* pkgname,
@@ -296,6 +298,489 @@
     return res;
 }
 
+int lookup_media_dir(char basepath[PATH_MAX], const char *dir)
+{
+    DIR *d;
+    struct dirent *de;
+    struct stat s;
+    char* dirpos = basepath + strlen(basepath);
+
+    if ((*(dirpos-1)) != '/') {
+        *dirpos = '/';
+        dirpos++;
+    }
+
+    CACHE_NOISY(ALOGI("Looking up %s in %s\n", dir, basepath));
+    // Verify the path won't extend beyond our buffer, to avoid
+    // repeated checking later.
+    if ((dirpos-basepath+strlen(dir)) >= (PATH_MAX-1)) {
+        ALOGW("Path exceeds limit: %s%s", basepath, dir);
+        return -1;
+    }
+
+    // First, can we find this directory with the case that is given?
+    strcpy(dirpos, dir);
+    if (stat(basepath, &s) >= 0) {
+        CACHE_NOISY(ALOGI("Found direct: %s\n", basepath));
+        return 0;
+    }
+
+    // Not found with that case...  search through all entries to find
+    // one that matches regardless of case.
+    *dirpos = 0;
+
+    d = opendir(basepath);
+    if (d == NULL) {
+        return -1;
+    }
+
+    while ((de = readdir(d))) {
+        if (strcasecmp(de->d_name, dir) == 0) {
+            strcpy(dirpos, de->d_name);
+            closedir(d);
+            CACHE_NOISY(ALOGI("Found search: %s\n", basepath));
+            return 0;
+        }
+    }
+
+    ALOGW("Couldn't find %s in %s", dir, basepath);
+    closedir(d);
+    return -1;
+}
+
+int64_t data_disk_free()
+{
+    struct statfs sfs;
+    if (statfs(android_data_dir.path, &sfs) == 0) {
+        return sfs.f_bavail * sfs.f_bsize;
+    } else {
+        ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
+        return -1;
+    }
+}
+
+cache_t* start_cache_collection()
+{
+    cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t));
+    return cache;
+}
+
+#define CACHE_BLOCK_SIZE (512*1024)
+
+static void* _cache_malloc(cache_t* cache, size_t len)
+{
+    len = (len+3)&~3;
+    if (len > (CACHE_BLOCK_SIZE/2)) {
+        // It doesn't make sense to try to put this allocation into one
+        // of our blocks, because it is so big.  Instead, make a new dedicated
+        // block for it.
+        int8_t* res = (int8_t*)malloc(len+sizeof(void*));
+        if (res == NULL) {
+            return NULL;
+        }
+        CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len));
+        // Link it into our list of blocks, not disrupting the current one.
+        if (cache->memBlocks == NULL) {
+            *(void**)res = NULL;
+            cache->memBlocks = res;
+        } else {
+            *(void**)res = *(void**)cache->memBlocks;
+            *(void**)cache->memBlocks = res;
+        }
+        return res + sizeof(void*);
+    }
+    int8_t* res = cache->curMemBlockAvail;
+    int8_t* nextPos = res + len;
+    if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) {
+        int8_t* newBlock = malloc(CACHE_BLOCK_SIZE);
+        if (newBlock == NULL) {
+            return NULL;
+        }
+        CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock));
+        *(void**)newBlock = cache->memBlocks;
+        cache->memBlocks = newBlock;
+        res = cache->curMemBlockAvail = newBlock + sizeof(void*);
+        cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE;
+        nextPos = res + len;
+    }
+    CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p",
+            res, len, cache->memBlocks, nextPos));
+    cache->curMemBlockAvail = nextPos;
+    return res;
+}
+
+static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len)
+{
+    // This isn't really a realloc, but it is good enough for our purposes here.
+    void* alloc = _cache_malloc(cache, len);
+    if (alloc != NULL && cur != NULL) {
+        memcpy(alloc, cur, origLen < len ? origLen : len);
+    }
+    return alloc;
+}
+
+static void _inc_num_cache_collected(cache_t* cache)
+{
+    cache->numCollected++;
+    if ((cache->numCollected%20000) == 0) {
+        ALOGI("Collected cache so far: %d directories, %d files",
+            cache->numDirs, cache->numFiles);
+    }
+}
+
+static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name)
+{
+    size_t nameLen = strlen(name);
+    cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1);
+    if (dir != NULL) {
+        dir->parent = parent;
+        dir->childCount = 0;
+        dir->hiddenCount = 0;
+        dir->deleted = 0;
+        strcpy(dir->name, name);
+        if (cache->numDirs >= cache->availDirs) {
+            size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2;
+            cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs,
+                    cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*));
+            if (newDirs == NULL) {
+                ALOGE("Failure growing cache dirs array for %s\n", name);
+                return NULL;
+            }
+            cache->availDirs = newAvail;
+            cache->dirs = newDirs;
+        }
+        cache->dirs[cache->numDirs] = dir;
+        cache->numDirs++;
+        if (parent != NULL) {
+            parent->childCount++;
+        }
+        _inc_num_cache_collected(cache);
+    } else {
+        ALOGE("Failure allocating cache_dir_t for %s\n", name);
+    }
+    return dir;
+}
+
+static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime,
+        const char *name)
+{
+    size_t nameLen = strlen(name);
+    cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1);
+    if (file != NULL) {
+        file->dir = dir;
+        file->modTime = modTime;
+        strcpy(file->name, name);
+        if (cache->numFiles >= cache->availFiles) {
+            size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2;
+            cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files,
+                    cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*));
+            if (newFiles == NULL) {
+                ALOGE("Failure growing cache file array for %s\n", name);
+                return NULL;
+            }
+            cache->availFiles = newAvail;
+            cache->files = newFiles;
+        }
+        CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file,
+                cache->numFiles, cache->files));
+        cache->files[cache->numFiles] = file;
+        cache->numFiles++;
+        dir->childCount++;
+        _inc_num_cache_collected(cache);
+    } else {
+        ALOGE("Failure allocating cache_file_t for %s\n", name);
+    }
+    return file;
+}
+
+static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName,
+        DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen)
+{
+    struct dirent *de;
+    cache_dir_t* cacheDir = NULL;
+    int dfd;
+
+    CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s",
+            parentDir, dirName, dir, pathBase));
+
+    dfd = dirfd(dir);
+
+    if (dfd < 0) return 0;
+
+    // Sub-directories always get added to the data structure, so if they
+    // are empty we will know about them to delete them later.
+    cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
+
+    while ((de = readdir(dir))) {
+        const char *name = de->d_name;
+
+        if (de->d_type == DT_DIR) {
+            int subfd;
+            DIR *subdir;
+
+                /* always skip "." and ".." */
+            if (name[0] == '.') {
+                if (name[1] == 0) continue;
+                if ((name[1] == '.') && (name[2] == 0)) continue;
+            }
+
+            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+            if (subfd < 0) {
+                ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
+                continue;
+            }
+            subdir = fdopendir(subfd);
+            if (subdir == NULL) {
+                ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
+                close(subfd);
+                continue;
+            }
+            if (cacheDir == NULL) {
+                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
+            }
+            if (cacheDir != NULL) {
+                // Update pathBase for the new path...  this may change dirName
+                // if that is also pointing to the path, but we are done with it
+                // now.
+                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
+                CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase));
+                if (finallen < pathAvailLen) {
+                    _add_cache_files(cache, cacheDir, name, subdir, pathBase,
+                            pathPos+finallen, pathAvailLen-finallen);
+                } else {
+                    // Whoops, the final path is too long!  We'll just delete
+                    // this directory.
+                    ALOGW("Cache dir %s truncated in path %s; deleting dir\n",
+                            name, pathBase);
+                    _delete_dir_contents(subdir, NULL);
+                    if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
+                        ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
+                    }
+                }
+            }
+            closedir(subdir);
+        } else if (de->d_type == DT_REG) {
+            // Skip files that start with '.'; they will be deleted if
+            // their entire directory is deleted.  This allows for metadata
+            // like ".nomedia" to remain in the directory until the entire
+            // directory is deleted.
+            if (cacheDir == NULL) {
+                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
+            }
+            if (name[0] == '.') {
+                cacheDir->hiddenCount++;
+                continue;
+            }
+            if (cacheDir != NULL) {
+                // Build final full path for file...  this may change dirName
+                // if that is also pointing to the path, but we are done with it
+                // now.
+                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
+                CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase));
+                if (finallen < pathAvailLen) {
+                    struct stat s;
+                    if (stat(pathBase, &s) >= 0) {
+                        _add_cache_file_t(cache, cacheDir, s.st_mtime, name);
+                    } else {
+                        ALOGW("Unable to stat cache file %s; deleting\n", pathBase);
+                        if (unlink(pathBase) < 0) {
+                            ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno));
+                        }
+                    }
+                } else {
+                    // Whoops, the final path is too long!  We'll just delete
+                    // this file.
+                    ALOGW("Cache file %s truncated in path %s; deleting\n",
+                            name, pathBase);
+                    if (unlinkat(dfd, name, 0) < 0) {
+                        *pathPos = 0;
+                        ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase,
+                                strerror(errno));
+                    }
+                }
+            }
+        } else {
+            cacheDir->hiddenCount++;
+        }
+    }
+    return 0;
+}
+
+void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir)
+{
+    DIR *d;
+    struct dirent *de;
+    char dirname[PATH_MAX];
+
+    CACHE_NOISY(ALOGI("add_cache_files: base=%s cachedir=%s\n", basepath, cachedir));
+
+    d = opendir(basepath);
+    if (d == NULL) {
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        if (de->d_type == DT_DIR) {
+            DIR* subdir;
+            const char *name = de->d_name;
+            char* pathpos;
+
+                /* always skip "." and ".." */
+            if (name[0] == '.') {
+                if (name[1] == 0) continue;
+                if ((name[1] == '.') && (name[2] == 0)) continue;
+            }
+
+            strcpy(dirname, basepath);
+            pathpos = dirname + strlen(dirname);
+            if ((*(pathpos-1)) != '/') {
+                *pathpos = '/';
+                pathpos++;
+                *pathpos = 0;
+            }
+            if (cachedir != NULL) {
+                snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/%s", name, cachedir);
+            } else {
+                snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s", name);
+            }
+            CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname));
+            subdir = opendir(dirname);
+            if (subdir != NULL) {
+                size_t dirnameLen = strlen(dirname);
+                _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen,
+                        PATH_MAX - dirnameLen);
+                closedir(subdir);
+            }
+        }
+    }
+
+    closedir(d);
+}
+
+static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir)
+{
+    char *pos = path;
+    if (dir->parent != NULL) {
+        pos = create_dir_path(path, dir->parent);
+    }
+    // Note that we don't need to worry about going beyond the buffer,
+    // since when we were constructing the cache entries our maximum
+    // buffer size for full paths was PATH_MAX.
+    strcpy(pos, dir->name);
+    pos += strlen(pos);
+    *pos = '/';
+    pos++;
+    *pos = 0;
+    return pos;
+}
+
+static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir)
+{
+    if (dir->parent != NULL) {
+        create_dir_path(path, dir);
+        ALOGI("DEL DIR %s\n", path);
+        if (dir->hiddenCount <= 0) {
+            if (rmdir(path)) {
+                ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno));
+                return;
+            }
+        } else {
+            // The directory contains hidden files so we need to delete
+            // them along with the directory itself.
+            if (delete_dir_contents(path, 1, NULL)) {
+                return;
+            }
+        }
+        dir->parent->childCount--;
+        dir->deleted = 1;
+        if (dir->parent->childCount <= 0) {
+            delete_cache_dir(path, dir->parent);
+        }
+    } else if (dir->hiddenCount > 0) {
+        // This is a root directory, but it has hidden files.  Get rid of
+        // all of those files, but not the directory itself.
+        create_dir_path(path, dir);
+        ALOGI("DEL CONTENTS %s\n", path);
+        delete_dir_contents(path, 0, NULL);
+    }
+}
+
+static int cache_modtime_sort(const void *lhsP, const void *rhsP)
+{
+    const cache_file_t *lhs = *(const cache_file_t**)lhsP;
+    const cache_file_t *rhs = *(const cache_file_t**)rhsP;
+    return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0);
+}
+
+void clear_cache_files(cache_t* cache, int64_t free_size)
+{
+    size_t i;
+    int skip = 0;
+    char path[PATH_MAX];
+
+    ALOGI("Collected cache files: %d directories, %d files",
+        cache->numDirs, cache->numFiles);
+
+    CACHE_NOISY(ALOGI("Sorting files..."));
+    qsort(cache->files, cache->numFiles, sizeof(cache_file_t*),
+            cache_modtime_sort);
+
+    CACHE_NOISY(ALOGI("Cleaning empty directories..."));
+    for (i=cache->numDirs; i>0; i--) {
+        cache_dir_t* dir = cache->dirs[i-1];
+        if (dir->childCount <= 0 && !dir->deleted) {
+            delete_cache_dir(path, dir);
+        }
+    }
+
+    CACHE_NOISY(ALOGI("Trimming files..."));
+    for (i=0; i<cache->numFiles; i++) {
+        skip++;
+        if (skip > 10) {
+            if (data_disk_free() > free_size) {
+                return;
+            }
+            skip = 0;
+        }
+        cache_file_t* file = cache->files[i];
+        strcpy(create_dir_path(path, file->dir), file->name);
+        ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path);
+        if (unlink(path) < 0) {
+            ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno));
+        }
+        file->dir->childCount--;
+        if (file->dir->childCount <= 0) {
+            delete_cache_dir(path, file->dir);
+        }
+    }
+}
+
+void finish_cache_collection(cache_t* cache)
+{
+    size_t i;
+
+    CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles));
+    CACHE_NOISY(
+        for (i=0; i<cache->numDirs; i++) {
+            cache_dir_t* dir = cache->dirs[i];
+            ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
+        })
+    CACHE_NOISY(
+        for (i=0; i<cache->numFiles; i++) {
+            cache_file_t* file = cache->files[i];
+            ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name,
+                    (int)file->modTime, file->dir);
+        })
+    void* block = cache->memBlocks;
+    while (block != NULL) {
+        void* nextBlock = *(void**)block;
+        CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block));
+        free(block);
+        block = nextBlock;
+    }
+    free(cache);
+}
+
 /**
  * Checks whether a path points to a system app (.apk file). Returns 0
  * if it is a system app or -1 if it is not.
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 88a025e..4cb5270 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -157,6 +157,11 @@
             return;
         }
 
+        if ("trim-caches".equals(op)) {
+            runTrimCaches();
+            return;
+        }
+
         if ("create-user".equals(op)) {
             runCreateUser();
             return;
@@ -1098,7 +1103,7 @@
         return obs.result;
     }
 
-    class ClearDataObserver extends IPackageDataObserver.Stub {
+    static class ClearDataObserver extends IPackageDataObserver.Stub {
         boolean finished;
         boolean result;
 
@@ -1272,6 +1277,75 @@
         }
     }
 
+    static class ClearCacheObserver extends IPackageDataObserver.Stub {
+        boolean finished;
+        boolean result;
+
+        @Override
+        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
+            synchronized (this) {
+                finished = true;
+                result = succeeded;
+                notifyAll();
+            }
+        }
+
+    }
+
+    private void runTrimCaches() {
+        String size = nextArg();
+        if (size == null) {
+            System.err.println("Error: no size specified");
+            showUsage();
+            return;
+        }
+        int len = size.length();
+        long multiplier = 1;
+        if (len > 1) {
+            char c = size.charAt(len-1);
+            if (c == 'K' || c == 'k') {
+                multiplier = 1024L;
+            } else if (c == 'M' || c == 'm') {
+                multiplier = 1024L*1024L;
+            } else if (c == 'G' || c == 'g') {
+                multiplier = 1024L*1024L*1024L;
+            } else {
+                System.err.println("Invalid suffix: " + c);
+                showUsage();
+                return;
+            }
+            size = size.substring(0, len-1);
+        }
+        long sizeVal;
+        try {
+            sizeVal = Long.parseLong(size) * multiplier;
+        } catch (NumberFormatException e) {
+            System.err.println("Error: expected number at: " + size);
+            showUsage();
+            return;
+        }
+        ClearDataObserver obs = new ClearDataObserver();
+        try {
+            mPm.freeStorageAndNotify(sizeVal, obs);
+            synchronized (obs) {
+                while (!obs.finished) {
+                    try {
+                        obs.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+        } catch (IllegalArgumentException e) {
+            System.err.println("Bad argument: " + e.toString());
+            showUsage();
+        } catch (SecurityException e) {
+            System.err.println("Operation not allowed: " + e.toString());
+        }
+    }
+
     /**
      * Displays the package file for a package.
      * @param pckg
@@ -1373,6 +1447,7 @@
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
         System.err.println("       pm get-install-location");
         System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
+        System.err.println("       pm trim-caches DESIRED_FREE_SPACE");
         System.err.println("");
         System.err.println("pm list packages: prints all packages, optionally only");
         System.err.println("  those whose package name contains the text in FILTER.  Options:");
@@ -1434,5 +1509,7 @@
         System.err.println("    0 [auto]: Let system decide the best location");
         System.err.println("    1 [internal]: Install on internal device storage");
         System.err.println("    2 [external]: Install on external media");
+        System.err.println("");
+        System.err.println("pm trim-caches: trim cache files to reach the given free space.");
     }
 }
diff --git a/cmds/sensorservice/Android.mk b/cmds/sensorservice/Android.mk
deleted file mode 100644
index 0811be5..0000000
--- a/cmds/sensorservice/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	main_sensorservice.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libsensorservice \
-	libbinder \
-	libutils
-
-LOCAL_C_INCLUDES := \
-	$(LOCAL_PATH)/../../services/sensorservice
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sensorservice
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 71c5622..3314dc3 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -33,6 +33,7 @@
     { AID_MEDIA, "media.audio_policy" },
     { AID_DRM,   "drm.drmManager" },
     { AID_NFC,   "nfc" },
+    { AID_BLUETOOTH, "bluetooth" },
     { AID_RADIO, "radio.phone" },
     { AID_RADIO, "radio.sms" },
     { AID_RADIO, "radio.phonesubinfo" },
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 9f92330..c42424c 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -8,7 +8,7 @@
 native = $(LOCAL_PATH)/../../../../native
 
 LOCAL_C_INCLUDES := \
-	$(base)/services/sensorservice \
+	$(native)/services/sensorservice \
 	$(native)/services/surfaceflinger \
 	$(JNI_H_INCLUDE)
 
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index cff16ff..2337790 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -918,6 +918,8 @@
             @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
             @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
             @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
+            @ViewDebug.IntToString(from = Gravity.START,             to = "START"),
+            @ViewDebug.IntToString(from = Gravity.END,               to = "END"),
             @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
             @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
             @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
@@ -925,7 +927,7 @@
             @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
             @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
         })
-        public int gravity = -1;
+        public int gravity = Gravity.NO_GRAVITY;
 
         public LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
@@ -933,13 +935,14 @@
             TypedArray a = c.obtainStyledAttributes(attrs,
                     com.android.internal.R.styleable.ActionBar_LayoutParams);
             gravity = a.getInt(
-                    com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity, -1);
+                    com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity,
+                    Gravity.NO_GRAVITY);
             a.recycle();
         }
 
         public LayoutParams(int width, int height) {
             super(width, height);
-            this.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;
+            this.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
         }
 
         public LayoutParams(int width, int height, int gravity) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f20fd33..809acac 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2708,7 +2708,12 @@
         // metadata is available.
         Intent upIntent = getParentActivityIntent();
         if (upIntent != null) {
-            if (shouldUpRecreateTask(upIntent)) {
+            if (mActivityInfo.taskAffinity == null) {
+                // Activities with a null affinity are special; they really shouldn't
+                // specify a parent activity intent in the first place. Just finish
+                // the current activity and call it a day.
+                finish();
+            } else if (shouldUpRecreateTask(upIntent)) {
                 TaskStackBuilder b = TaskStackBuilder.create(this);
                 onCreateNavigateUpTaskStack(b);
                 onPrepareNavigateUpTaskStack(b);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7242029..7011bc1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -70,6 +70,7 @@
 import android.util.LogPrinter;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
+import android.view.CompatibilityInfoHolder;
 import android.view.Display;
 import android.view.HardwareRenderer;
 import android.view.View;
@@ -1527,7 +1528,9 @@
             dm = new DisplayMetrics();
             mDisplayMetrics.put(ci, dm);
         }
-        Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay();
+        CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
+        cih.set(ci);
+        Display d = WindowManagerImpl.getDefault().makeCompatible(cih).getDefaultDisplay();
         d.getMetrics(dm);
         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
         //        + metrics.heightPixels + " den=" + metrics.density
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 191a696..9a50a41 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1206,7 +1206,8 @@
             return mPM.getUsers();
         } catch (RemoteException re) {
             ArrayList<UserInfo> users = new ArrayList<UserInfo>();
-            UserInfo primary = new UserInfo(0, "Root!", UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
+            UserInfo primary = new UserInfo(0, "Root!", null,
+                    UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
             users.add(primary);
             return users;
         }
@@ -1240,9 +1241,9 @@
      * @hide
      */
     @Override
-    public void updateUserName(int id, String name) {
+    public void setUserName(int id, String name) {
         try {
-            mPM.updateUserName(id, name);
+            mPM.setUserName(id, name);
         } catch (RemoteException re) {
         }
     }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b902550..9364a57 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.policy.PolicyManager;
 
+import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -294,6 +295,11 @@
                     return new MediaRouter(ctx);
                 }});
 
+        registerService(BLUETOOTH_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return BluetoothAdapter.getDefaultAdapter();
+                }});
+
         registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return new ClipboardManager(ctx.getOuterContext(),
@@ -361,10 +367,10 @@
                     return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
                 }});
 
-        registerService(LOCATION_SERVICE, new StaticServiceFetcher() {
-                public Object createStaticService() {
+        registerService(LOCATION_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(LOCATION_SERVICE);
-                    return new LocationManager(ILocationManager.Stub.asInterface(b));
+                    return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
                 }});
 
         registerService(NETWORK_POLICY_SERVICE, new ServiceFetcher() {
@@ -483,7 +489,8 @@
 
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
-                    return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
+                    return WindowManagerImpl.getDefault().makeCompatible(
+                            ctx.mPackageInfo.mCompatibilityInfo);
                 }});
     }
 
@@ -1187,6 +1194,9 @@
     @Override
     public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
         IServiceConnection sd;
+        if (conn == null) {
+            throw new IllegalArgumentException("connection is null");
+        }
         if (mPackageInfo != null) {
             sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                     mMainThread.getHandler(), flags);
@@ -1217,6 +1227,9 @@
 
     @Override
     public void unbindService(ServiceConnection conn) {
+        if (conn == null) {
+            throw new IllegalArgumentException("connection is null");
+        }
         if (mPackageInfo != null) {
             IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
                     getOuterContext(), conn);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 39e2423..1bf7785 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,6 +22,8 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.os.Bundle;
+// TODO(cmautner): remove after fixing 6829431.
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
@@ -383,7 +385,8 @@
  * Container for fragments associated with an activity.
  */
 final class FragmentManagerImpl extends FragmentManager {
-    static boolean DEBUG = false;
+    // TODO(cmautner): restore to false after fixing 6829431.
+    static boolean DEBUG = true;
     static final String TAG = "FragmentManager";
     
     static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
@@ -732,6 +735,10 @@
 
     void moveToState(Fragment f, int newState, int transit, int transitionStyle,
             boolean keepActive) {
+        // TODO(cmautner): remove after fixing 6829431.
+        if (DEBUG) Log.v(TAG, "moveToState: " + f
+            + " oldState=" + f.mState + " newState=" + newState
+            + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5));
         // Fragments that are not currently added will sit in the onCreate() state.
         if (!f.mAdded && newState > Fragment.CREATED) {
             newState = Fragment.CREATED;
@@ -1923,7 +1930,7 @@
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mUserVisibleHint) {
+                if (f != null && !f.mHidden) {
                     if (f.onContextItemSelected(item)) {
                         return true;
                     }
diff --git a/core/java/android/app/IInstrumentationWatcher.aidl b/core/java/android/app/IInstrumentationWatcher.aidl
index 405a3d8..6c8c4d6 100644
--- a/core/java/android/app/IInstrumentationWatcher.aidl
+++ b/core/java/android/app/IInstrumentationWatcher.aidl
@@ -21,7 +21,7 @@
 import android.os.Bundle;
 
 /** @hide */
-oneway interface IInstrumentationWatcher
+interface IInstrumentationWatcher
 {
     void instrumentationStatus(in ComponentName name, int resultCode,
             in Bundle results);
diff --git a/core/java/android/app/MediaRouteActionProvider.java b/core/java/android/app/MediaRouteActionProvider.java
index c2f5ac1..5b5506d 100644
--- a/core/java/android/app/MediaRouteActionProvider.java
+++ b/core/java/android/app/MediaRouteActionProvider.java
@@ -26,6 +26,7 @@
 import android.view.ActionProvider;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 
 import java.lang.ref.WeakReference;
 
@@ -82,6 +83,8 @@
         mView = new MediaRouteButton(mContext);
         mView.setRouteTypes(mRouteTypes);
         mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
+        mView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
         return mView;
     }
 
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 35cc324..396f910 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -1,6 +1,5 @@
 package android.app;
 
-import com.android.internal.view.IInputMethodCallback;
 import com.android.internal.view.IInputMethodSession;
 
 import android.content.Context;
@@ -119,7 +118,7 @@
         }
     }
     
-    static class InputMethodCallback extends IInputMethodCallback.Stub {
+    static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
         WeakReference<NativeActivity> mNa;
 
         InputMethodCallback(NativeActivity na) {
@@ -133,11 +132,6 @@
                 na.finishPreDispatchKeyEventNative(na.mNativeHandle, seq, handled);
             }
         }
-
-        @Override
-        public void sessionCreated(IInputMethodSession session) {
-            // Stub -- not for use in the client.
-        }
     }
 
     @Override
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 08bc0ac..2c19c0c 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -41,7 +41,8 @@
 
     static final int HANDLE_UPDATE = 1;
     static final int HANDLE_PROVIDER_CHANGED = 2;
-    static final int HANDLE_VIEW_DATA_CHANGED = 3;
+    static final int HANDLE_PROVIDERS_CHANGED = 3;
+    static final int HANDLE_VIEW_DATA_CHANGED = 4;
 
     final static Object sServiceLock = new Object();
     static IAppWidgetService sService;
@@ -65,6 +66,11 @@
             msg.sendToTarget();
         }
 
+        public void providersChanged() {
+            Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED);
+            msg.sendToTarget();
+        }
+
         public void viewDataChanged(int appWidgetId, int viewId) {
             Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED);
             msg.arg1 = appWidgetId;
@@ -88,6 +94,10 @@
                     onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj);
                     break;
                 }
+                case HANDLE_PROVIDERS_CHANGED: {
+                    onProvidersChanged();
+                    break;
+                }
                 case HANDLE_VIEW_DATA_CHANGED: {
                     viewDataChanged(msg.arg1, msg.arg2);
                     break;
@@ -274,6 +284,14 @@
         }
     }
 
+    /**
+     * Called when the set of available widgets changes (ie. widget containing packages
+     * are added, updated or removed, or widget components are enabled or disabled.)
+     */
+    protected void onProvidersChanged() {
+        // Do nothing
+    }
+
     void updateAppWidgetView(int appWidgetId, RemoteViews views) {
         AppWidgetHostView v;
         synchronized (mViews) {
diff --git a/core/java/android/bluetooth/AtCommandHandler.java b/core/java/android/bluetooth/AtCommandHandler.java
deleted file mode 100644
index 6deab34..0000000
--- a/core/java/android/bluetooth/AtCommandHandler.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.AtCommandResult;
-
-/**
- * Handler Interface for {@link AtParser}.<p>
- * @hide
- */
-public abstract class AtCommandHandler {
-
-    /**
-     * Handle Basic commands "ATA".<p>
-     * These are single letter commands such as ATA and ATD. Anything following
-     * the single letter command ('A' and 'D' respectively) will be passed as
-     * 'arg'.<p>
-     * For example, "ATDT1234" would result in the call
-     * handleBasicCommand("T1234").<p>
-     * @param arg Everything following the basic command character.
-     * @return    The result of this command.
-     */
-    public AtCommandResult handleBasicCommand(String arg) {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Actions command "AT+FOO".<p>
-     * Action commands are part of the Extended command syntax, and are
-     * typically used to signal an action on "FOO".<p>
-     * @return The result of this command.
-     */
-    public AtCommandResult handleActionCommand() {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Read command "AT+FOO?".<p>
-     * Read commands are part of the Extended command syntax, and are
-     * typically used to read the value of "FOO".<p>
-     * @return The result of this command.
-     */
-    public AtCommandResult handleReadCommand() {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Set command "AT+FOO=...".<p>
-     * Set commands are part of the Extended command syntax, and are
-     * typically used to set the value of "FOO". Multiple arguments can be
-     * sent.<p>
-     * AT+FOO=[<arg1>[,<arg2>[,...]]]<p>
-     * Each argument will be either numeric (Integer) or String.
-     * handleSetCommand is passed a generic Object[] array in which each
-     * element will be an Integer (if it can be parsed with parseInt()) or
-     * String.<p>
-     * Missing arguments ",," are set to empty Strings.<p>
-     * @param args Array of String and/or Integer's. There will always be at
-     *             least one element in this array.
-     * @return     The result of this command.
-     */
-    // Typically used to set this parameter
-    public AtCommandResult handleSetCommand(Object[] args) {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Test command "AT+FOO=?".<p>
-     * Test commands are part of the Extended command syntax, and are typically
-     * used to request an indication of the range of legal values that "FOO"
-     * can take.<p>
-     * By default we return an OK result, to indicate that this command is at
-     * least recognized.<p>
-     * @return The result of this command.
-     */
-    public AtCommandResult handleTestCommand() {
-        return new AtCommandResult(AtCommandResult.OK);
-    }
-
-}
diff --git a/core/java/android/bluetooth/AtCommandResult.java b/core/java/android/bluetooth/AtCommandResult.java
deleted file mode 100644
index 9675234..0000000
--- a/core/java/android/bluetooth/AtCommandResult.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * The result of execution of a single AT command.<p>
- *
- *
- * This class can represent the final response to an AT command line, and also
- * intermediate responses to a single command within a chained AT command
- * line.<p>
- *
- * The actual responses that are intended to be send in reply to the AT command
- * line are stored in a string array. The final response is stored as an
- * int enum, converted to a string when toString() is called. Only a single
- * final response is sent from multiple commands chained into a single command
- * line.<p>
- * @hide
- */
-public class AtCommandResult {
-    // Result code enumerations
-    public static final int OK = 0;
-    public static final int ERROR = 1;
-    public static final int UNSOLICITED = 2;
-
-    private static final String OK_STRING = "OK";
-    private static final String ERROR_STRING = "ERROR";
-
-    private int mResultCode;  // Result code
-    private StringBuilder mResponse; // Response with CRLF line breaks
-
-    /**
-     * Construct a new AtCommandResult with given result code, and an empty
-     * response array.
-     * @param resultCode One of OK, ERROR or UNSOLICITED.
-     */
-    public AtCommandResult(int resultCode) {
-        mResultCode = resultCode;
-        mResponse = new StringBuilder();
-    }
-
-    /**
-     * Construct a new AtCommandResult with result code OK, and the specified
-     * single line response.
-     * @param response The single line response.
-     */
-    public AtCommandResult(String response) {
-        this(OK);
-        addResponse(response);
-    }
-
-    public int getResultCode() {
-        return mResultCode;
-    }
-
-    /**
-     * Add another line to the response.
-     */
-    public void addResponse(String response) {
-        appendWithCrlf(mResponse, response);
-    }
-
-    /**
-     * Add the given result into this AtCommandResult object.<p>
-     * Used to combine results from multiple commands in a single command line
-     * (command chaining).
-     * @param result The AtCommandResult to add to this result.
-     */
-    public void addResult(AtCommandResult result) {
-        if (result != null) {
-            appendWithCrlf(mResponse, result.mResponse.toString());
-            mResultCode = result.mResultCode;
-        }
-    }
-
-    /**
-     * Generate the string response ready to send
-     */
-    public String toString() {
-        StringBuilder result = new StringBuilder(mResponse.toString());
-        switch (mResultCode) {
-        case OK:
-            appendWithCrlf(result, OK_STRING);
-            break;
-        case ERROR:
-            appendWithCrlf(result, ERROR_STRING);
-            break;
-        }
-        return result.toString();
-    }
-
-    /** Append a string to a string builder, joining with a double
-     * CRLF. Used to create multi-line AT command replies
-     */
-    public static void appendWithCrlf(StringBuilder str1, String str2) {
-        if (str1.length() > 0 && str2.length() > 0) {
-            str1.append("\r\n\r\n");
-        }
-        str1.append(str2);
-    }
-};
diff --git a/core/java/android/bluetooth/AtParser.java b/core/java/android/bluetooth/AtParser.java
deleted file mode 100644
index 328fb2b..0000000
--- a/core/java/android/bluetooth/AtParser.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import java.util.*;
-
-/**
- * An AT (Hayes command) Parser based on (a subset of) the ITU-T V.250 standard.
- * <p>
- *
- * Conformant with the subset of V.250 required for implementation of the
- * Bluetooth Headset and Handsfree Profiles, as per Bluetooth SIP
- * specifications. Also implements some V.250 features not required by
- * Bluetooth - such as chained commands.<p>
- *
- * Command handlers are registered with an AtParser object. These handlers are
- * invoked when command lines are processed by AtParser's process() method.<p>
- *
- * The AtParser object accepts a new command line to parse via its process()
- * method. It breaks each command line into one or more commands. Each command
- * is parsed for name, type, and (optional) arguments, and an appropriate
- * external handler method is called through the AtCommandHandler interface.
- *
- * The command types are<ul>
- * <li>Basic Command. For example "ATDT1234567890". Basic command names are a
- * single character (e.g. "D"), and everything following this character is
- * passed to the handler as a string argument (e.g. "T1234567890").
- * <li>Action Command. For example "AT+CIMI". The command name is "CIMI", and
- * there are no arguments for action commands.
- * <li>Read Command. For example "AT+VGM?". The command name is "VGM", and there
- * are no arguments for get commands.
- * <li>Set Command. For example "AT+VGM=14". The command name is "VGM", and
- * there is a single integer argument in this case. In the general case then
- * can be zero or more arguments (comma delimited) each of integer or string
- * form.
- * <li>Test Command. For example "AT+VGM=?. No arguments.
- * </ul>
- *
- * In V.250 the last four command types are known as Extended Commands, and
- * they are used heavily in Bluetooth.<p>
- *
- * Basic commands cannot be chained in this implementation. For Bluetooth
- * headset/handsfree use this is acceptable, because they only use the basic
- * commands ATA and ATD, which are not allowed to be chained. For general V.250
- * use we would need to improve this class to allow Basic command chaining -
- * however it's tricky to get right because there is no delimiter for Basic
- * command chaining.<p>
- *
- * Extended commands can be chained. For example:<p>
- * AT+VGM?;+VGM=14;+CIMI<p>
- * This is equivalent to:<p>
- * AT+VGM?
- * AT+VGM=14
- * AT+CIMI
- * Except that only one final result code is return (although several
- * intermediate responses may be returned), and as soon as one command in the
- * chain fails the rest are abandoned.<p>
- *
- * Handlers are registered by there command name via register(Char c, ...) or
- * register(String s, ...). Handlers for Basic command should be registered by
- * the basic command character, and handlers for Extended commands should be
- * registered by String.<p>
- *
- * Refer to:<ul>
- * <li>ITU-T Recommendation V.250
- * <li>ETSI TS 127.007  (AT Command set for User Equipment, 3GPP TS 27.007)
- * <li>Bluetooth Headset Profile Spec (K6)
- * <li>Bluetooth Handsfree Profile Spec (HFP 1.5)
- * </ul>
- * @hide
- */
-public class AtParser {
-
-    // Extended command type enumeration, only used internally
-    private static final int TYPE_ACTION = 0;   // AT+FOO
-    private static final int TYPE_READ = 1;     // AT+FOO?
-    private static final int TYPE_SET = 2;      // AT+FOO=
-    private static final int TYPE_TEST = 3;     // AT+FOO=?
-
-    private HashMap<String, AtCommandHandler> mExtHandlers;
-    private HashMap<Character, AtCommandHandler> mBasicHandlers;
-
-    private String mLastInput;  // for "A/" (repeat last command) support
-
-    /**
-     * Create a new AtParser.<p>
-     * No handlers are registered.
-     */
-    public AtParser() {
-        mBasicHandlers = new HashMap<Character, AtCommandHandler>();
-        mExtHandlers = new HashMap<String, AtCommandHandler>();
-        mLastInput = "";
-    }
-
-    /**
-     * Register a Basic command handler.<p>
-     * Basic command handlers are later called via their
-     * <code>handleBasicCommand(String args)</code> method.
-     * @param  command Command name - a single character
-     * @param  handler Handler to register
-     */
-    public void register(Character command, AtCommandHandler handler) {
-        mBasicHandlers.put(command, handler);
-    }
-
-    /**
-     * Register an Extended command handler.<p>
-     * Extended command handlers are later called via:<ul>
-     * <li><code>handleActionCommand()</code>
-     * <li><code>handleGetCommand()</code>
-     * <li><code>handleSetCommand()</code>
-     * <li><code>handleTestCommand()</code>
-     * </ul>
-     * Only one method will be called for each command processed.
-     * @param  command Command name - can be multiple characters
-     * @param  handler Handler to register
-     */
-    public void register(String command, AtCommandHandler handler) {
-        mExtHandlers.put(command, handler);
-    }
-
-
-    /**
-     * Strip input of whitespace and force Uppercase - except sections inside
-     * quotes. Also fixes unmatched quotes (by appending a quote). Double
-     * quotes " are the only quotes allowed by V.250
-     */
-    static private String clean(String input) {
-        StringBuilder out = new StringBuilder(input.length());
-
-        for (int i = 0; i < input.length(); i++) {
-            char c = input.charAt(i);
-            if (c == '"') {
-                int j = input.indexOf('"', i + 1 );  // search for closing "
-                if (j == -1) {  // unmatched ", insert one.
-                    out.append(input.substring(i, input.length()));
-                    out.append('"');
-                    break;
-                }
-                out.append(input.substring(i, j + 1));
-                i = j;
-            } else if (c != ' ') {
-                out.append(Character.toUpperCase(c));
-            }
-        }
-
-        return out.toString();
-    }
-
-    static private boolean isAtoZ(char c) {
-        return (c >= 'A' && c <= 'Z');
-    }
-
-    /**
-     * Find a character ch, ignoring quoted sections.
-     * Return input.length() if not found.
-     */
-    static private int findChar(char ch, String input, int fromIndex) {
-        for (int i = fromIndex; i < input.length(); i++) {
-            char c = input.charAt(i);
-            if (c == '"') {
-                i = input.indexOf('"', i + 1);
-                if (i == -1) {
-                    return input.length();
-                }
-            } else if (c == ch) {
-                return i;
-            }
-        }
-        return input.length();
-    }
-
-    /**
-     * Break an argument string into individual arguments (comma delimited).
-     * Integer arguments are turned into Integer objects. Otherwise a String
-     * object is used.
-     */
-    static private Object[] generateArgs(String input) {
-        int i = 0;
-        int j;
-        ArrayList<Object> out = new ArrayList<Object>();
-        while (i <= input.length()) {
-            j = findChar(',', input, i);
-
-            String arg = input.substring(i, j);
-            try {
-                out.add(new Integer(arg));
-            } catch (NumberFormatException e) {
-                out.add(arg);
-            }
-
-            i = j + 1; // move past comma
-        }
-        return out.toArray();
-    }
-
-    /**
-     * Return the index of the end of character after the last character in
-     * the extended command name. Uses the V.250 spec for allowed command
-     * names.
-     */
-    static private int findEndExtendedName(String input, int index) {
-        for (int i = index; i < input.length(); i++) {
-            char c = input.charAt(i);
-
-            // V.250 defines the following chars as legal extended command
-            // names
-            if (isAtoZ(c)) continue;
-            if (c >= '0' && c <= '9') continue;
-            switch (c) {
-            case '!':
-            case '%':
-            case '-':
-            case '.':
-            case '/':
-            case ':':
-            case '_':
-                continue;
-            default:
-                return i;
-            }
-        }
-        return input.length();
-    }
-
-    /**
-     * Processes an incoming AT command line.<p>
-     * This method will invoke zero or one command handler methods for each
-     * command in the command line.<p>
-     * @param raw_input The AT input, without EOL delimiter (e.g. <CR>).
-     * @return          Result object for this command line. This can be
-     *                  converted to a String[] response with toStrings().
-     */
-    public AtCommandResult process(String raw_input) {
-        String input = clean(raw_input);
-
-        // Handle "A/" (repeat previous line)
-        if (input.regionMatches(0, "A/", 0, 2)) {
-            input = new String(mLastInput);
-        } else {
-            mLastInput = new String(input);
-        }
-
-        // Handle empty line - no response necessary
-        if (input.equals("")) {
-            // Return []
-            return new AtCommandResult(AtCommandResult.UNSOLICITED);
-        }
-
-        // Anything else deserves an error
-        if (!input.regionMatches(0, "AT", 0, 2)) {
-            // Return ["ERROR"]
-            return new AtCommandResult(AtCommandResult.ERROR);
-        }
-
-        // Ok we have a command that starts with AT. Process it
-        int index = 2;
-        AtCommandResult result =
-                new AtCommandResult(AtCommandResult.UNSOLICITED);
-        while (index < input.length()) {
-            char c = input.charAt(index);
-
-            if (isAtoZ(c)) {
-                // Option 1: Basic Command
-                // Pass the rest of the line as is to the handler. Do not
-                // look for any more commands on this line.
-                String args = input.substring(index + 1);
-                if (mBasicHandlers.containsKey((Character)c)) {
-                    result.addResult(mBasicHandlers.get(
-                            (Character)c).handleBasicCommand(args));
-                    return result;
-                } else {
-                    // no handler
-                    result.addResult(
-                            new AtCommandResult(AtCommandResult.ERROR));
-                    return result;
-                }
-                // control never reaches here
-            }
-
-            if (c == '+') {
-                // Option 2: Extended Command
-                // Search for first non-name character. Short-circuit if
-                // we don't handle this command name.
-                int i = findEndExtendedName(input, index + 1);
-                String commandName = input.substring(index, i);
-                if (!mExtHandlers.containsKey(commandName)) {
-                    // no handler
-                    result.addResult(
-                            new AtCommandResult(AtCommandResult.ERROR));
-                    return result;
-                }
-                AtCommandHandler handler = mExtHandlers.get(commandName);
-
-                // Search for end of this command - this is usually the end of
-                // line
-                int endIndex = findChar(';', input, index);
-
-                // Determine what type of command this is.
-                // Default to TYPE_ACTION if we can't find anything else
-                // obvious.
-                int type;
-
-                if (i >= endIndex) {
-                    type = TYPE_ACTION;
-                } else if (input.charAt(i) == '?') {
-                    type = TYPE_READ;
-                } else if (input.charAt(i) == '=') {
-                    if (i + 1 < endIndex) {
-                        if (input.charAt(i + 1) == '?') {
-                            type = TYPE_TEST;
-                        } else {
-                            type = TYPE_SET;
-                        }
-                    } else {
-                        type = TYPE_SET;
-                    }
-                } else {
-                    type = TYPE_ACTION;
-                }
-
-                // Call this command. Short-circuit as soon as a command fails
-                switch (type) {
-                case TYPE_ACTION:
-                    result.addResult(handler.handleActionCommand());
-                    break;
-                case TYPE_READ:
-                    result.addResult(handler.handleReadCommand());
-                    break;
-                case TYPE_TEST:
-                    result.addResult(handler.handleTestCommand());
-                    break;
-                case TYPE_SET:
-                    Object[] args =
-                            generateArgs(input.substring(i + 1, endIndex));
-                    result.addResult(handler.handleSetCommand(args));
-                    break;
-                }
-                if (result.getResultCode() != AtCommandResult.OK) {
-                    return result;   // short-circuit
-                }
-
-                index = endIndex;
-            } else {
-                // Can't tell if this is a basic or extended command.
-                // Push forwards and hope we hit something.
-                index++;
-            }
-        }
-        // Finished processing (and all results were ok)
-        return result;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
old mode 100644
new mode 100755
index 7300107..74f634b
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -18,12 +18,13 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.server.BluetoothA2dpService;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -43,7 +44,7 @@
  */
 public final class BluetoothA2dp implements BluetoothProfile {
     private static final String TAG = "BluetoothA2dp";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the A2DP
@@ -102,37 +103,90 @@
      */
     public static final int STATE_NOT_PLAYING   =  11;
 
+    private Context mContext;
     private ServiceListener mServiceListener;
     private IBluetoothA2dp mService;
     private BluetoothAdapter mAdapter;
 
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (DBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (DBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothA2dp.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth A2DP Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
     /**
      * Create a BluetoothA2dp proxy object for interacting with the local
      * Bluetooth A2DP service.
      *
      */
-    /*package*/ BluetoothA2dp(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
+    /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetoothA2dp.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this);
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
             }
-        } else {
-            Log.w(TAG, "Bluetooth A2DP service not available!");
+        }
 
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        if (!context.bindService(new Intent(IBluetoothA2dp.class.getName()), mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth A2DP Service");
         }
     }
 
     /*package*/ void close() {
         mServiceListener = null;
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
+        }
     }
 
+    public void finalize() {
+        close();
+    }
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
@@ -267,7 +321,7 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     *  Priority can be one of {@link #PRIORITY_ON} or
+     *  Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
      * {@link #PRIORITY_OFF},
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
@@ -283,7 +337,8 @@
         if (mService != null && isEnabled()
             && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
+                priority != BluetoothProfile.PRIORITY_ON &&
+                priority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
               return false;
             }
             try {
@@ -347,67 +402,6 @@
     }
 
     /**
-     * Initiate suspend from an A2DP sink.
-     *
-     * <p> This API will return false in scenarios like the A2DP
-     * device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that {@link #ACTION_CONNECTION_STATE_CHANGED}
-     * intent will be broadcasted with the state. Users can get the
-     * state of the A2DP device from this intent.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
-     *
-     * @param device Remote A2DP sink
-     * @return false on immediate error,
-     *               true otherwise
-     * @hide
-     */
-    public boolean suspendSink(BluetoothDevice device) {
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
-            try {
-                return mService.suspendSink(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-                return false;
-            }
-        }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
-        return false;
-    }
-
-    /**
-     * Initiate resume from a suspended A2DP sink.
-     *
-     * <p> This API will return false in scenarios like the A2DP
-     * device is not in suspended state etc. When this API returns,
-     * true, it is guaranteed that {@link #ACTION_SINK_STATE_CHANGED}
-     * intent will be broadcasted with the state. Users can get the
-     * state of the A2DP device from this intent.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     *
-     * @param device Remote A2DP sink
-     * @return false on immediate error,
-     *               true otherwise
-     * @hide
-     */
-    public boolean resumeSink(BluetoothDevice device) {
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
-            try {
-                return mService.resumeSink(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-                return false;
-            }
-        }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
-        return false;
-    }
-
-    /**
      * This function checks if the remote device is an AVCRP
      * target and thus whether we should send volume keys
      * changes or not.
@@ -428,23 +422,6 @@
     }
 
     /**
-     * Allow or disallow incoming connection
-     * @param device Sink
-     * @param value True / False
-     * @return Success or Failure of the binder call.
-     * @hide
-     */
-    public boolean allowIncomingConnect(BluetoothDevice device, boolean value) {
-        if (DBG) log("allowIncomingConnect(" + device + ":" + value + ")");
-        try {
-            return mService.allowIncomingConnect(device, value);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-    }
-
-    /**
      * Helper for converting a state to a string.
      *
      * For debug use only - strings are not internationalized.
@@ -469,6 +446,24 @@
         }
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothA2dp.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
+            }
+        }
+    };
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
old mode 100644
new mode 100755
index 8e3df47..dc18029
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -31,6 +31,7 @@
 import android.util.Pair;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -73,7 +74,7 @@
  */
 public final class BluetoothAdapter {
     private static final String TAG = "BluetoothAdapter";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Sentinel error value for this class. Guaranteed to not equal any other
@@ -343,7 +344,7 @@
     public static final int STATE_DISCONNECTING = 3;
 
     /** @hide */
-    public static final String BLUETOOTH_SERVICE = "bluetooth";
+    public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
 
     private static final int ADDRESS_LENGTH = 17;
 
@@ -353,7 +354,8 @@
      */
     private static BluetoothAdapter sAdapter;
 
-    private final IBluetooth mService;
+    private final IBluetoothManager mManagerService;
+    private IBluetooth mService;
 
     private Handler mServiceRecordHandler;
 
@@ -367,10 +369,12 @@
      */
     public static synchronized BluetoothAdapter getDefaultAdapter() {
         if (sAdapter == null) {
-            IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+            IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
             if (b != null) {
-                IBluetooth service = IBluetooth.Stub.asInterface(b);
-                sAdapter = new BluetoothAdapter(service);
+                IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
+                sAdapter = new BluetoothAdapter(managerService);
+            } else {
+                Log.e(TAG, "Bluetooth binder is null");
             }
         }
         return sAdapter;
@@ -378,13 +382,16 @@
 
     /**
      * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
-     * @hide
      */
-    public BluetoothAdapter(IBluetooth service) {
-        if (service == null) {
-            throw new IllegalArgumentException("service is null");
+    BluetoothAdapter(IBluetoothManager managerService) {
+
+        if (managerService == null) {
+            throw new IllegalArgumentException("bluetooth manager service is null");
         }
-        mService = service;
+        try {
+            mService = managerService.registerAdapter(mManagerCallback);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        mManagerService = managerService;
         mServiceRecordHandler = null;
     }
 
@@ -432,8 +439,11 @@
      * @return true if the local adapter is turned on
      */
     public boolean isEnabled() {
+
         try {
-            return mService.isEnabled();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.isEnabled();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -451,8 +461,18 @@
      */
     public int getState() {
         try {
-            return mService.getBluetoothState();
+            synchronized(mManagerCallback) {
+                if (mService != null)
+                {
+                    int state=  mService.getState();
+                    if (DBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state);
+                    return state;
+                }
+                // TODO(BT) there might be a small gap during STATE_TURNING_ON that
+                //          mService is null, handle that case
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
+        if (DBG) Log.d(TAG, "" + hashCode() + ": getState() :  mService = null. Returning STATE_OFF");
         return STATE_OFF;
     }
 
@@ -484,8 +504,9 @@
      *         immediate error
      */
     public boolean enable() {
+        boolean enabled = false;
         try {
-            return mService.enable();
+            return mManagerService.enable();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -516,7 +537,25 @@
      */
     public boolean disable() {
         try {
-            return mService.disable(true);
+            return mManagerService.disable(true);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return false;
+    }
+
+    /**
+     * Turn off the local Bluetooth adapter and don't persist the setting.
+     *
+     * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     * permission
+     *
+     * @return true to indicate adapter shutdown has begun, or false on
+     *         immediate error
+     * @hide
+     */
+    public boolean disable(boolean persist) {
+
+        try {
+            return mManagerService.disable(persist);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -530,7 +569,7 @@
      */
     public String getAddress() {
         try {
-            return mService.getAddress();
+            return mManagerService.getAddress();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -544,7 +583,7 @@
      */
     public String getName() {
         try {
-            return mService.getName();
+            return mManagerService.getName();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -560,7 +599,9 @@
     public ParcelUuid[] getUuids() {
         if (getState() != STATE_ON) return null;
         try {
-            return mService.getUuids();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getUuids();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -583,7 +624,9 @@
     public boolean setName(String name) {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.setName(name);
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.setName(name);
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -607,7 +650,9 @@
     public int getScanMode() {
         if (getState() != STATE_ON) return SCAN_MODE_NONE;
         try {
-            return mService.getScanMode();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getScanMode();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return SCAN_MODE_NONE;
     }
@@ -643,7 +688,9 @@
     public boolean setScanMode(int mode, int duration) {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.setScanMode(mode, duration);
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.setScanMode(mode, duration);
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -651,14 +698,17 @@
     /** @hide */
     public boolean setScanMode(int mode) {
         if (getState() != STATE_ON) return false;
-        return setScanMode(mode, 120);
+        /* getDiscoverableTimeout() to use the latest from NV than use 0 */
+        return setScanMode(mode, getDiscoverableTimeout());
     }
 
     /** @hide */
     public int getDiscoverableTimeout() {
         if (getState() != STATE_ON) return -1;
         try {
-            return mService.getDiscoverableTimeout();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getDiscoverableTimeout();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return -1;
     }
@@ -667,7 +717,9 @@
     public void setDiscoverableTimeout(int timeout) {
         if (getState() != STATE_ON) return;
         try {
-            mService.setDiscoverableTimeout(timeout);
+            synchronized(mManagerCallback) {
+                if (mService != null) mService.setDiscoverableTimeout(timeout);
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
     }
 
@@ -704,7 +756,9 @@
     public boolean startDiscovery() {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.startDiscovery();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.startDiscovery();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -729,7 +783,9 @@
     public boolean cancelDiscovery() {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.cancelDiscovery();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.cancelDiscovery();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -756,7 +812,9 @@
     public boolean isDiscovering() {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.isDiscovering();
+            synchronized(mManagerCallback) {
+                if (mService != null ) return mService.isDiscovering();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -774,10 +832,13 @@
      */
     public Set<BluetoothDevice> getBondedDevices() {
         if (getState() != STATE_ON) {
-            return toDeviceSet(new String[0]);
+            return toDeviceSet(new BluetoothDevice[0]);
         }
         try {
-            return toDeviceSet(mService.listBonds());
+            synchronized(mManagerCallback) {
+                if (mService != null) return toDeviceSet(mService.getBondedDevices());
+            }
+            return toDeviceSet(new BluetoothDevice[0]);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -798,7 +859,9 @@
     public int getConnectionState() {
         if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
         try {
-            return mService.getAdapterConnectionState();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getAdapterConnectionState();
+            }
         } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);}
         return BluetoothAdapter.STATE_DISCONNECTED;
     }
@@ -821,7 +884,9 @@
     public int getProfileConnectionState(int profile) {
         if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
         try {
-            return mService.getProfileConnectionState(profile);
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getProfileConnectionState(profile);
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "getProfileConnectionState:", e);
         }
@@ -829,51 +894,6 @@
     }
 
     /**
-    /**
-     * Picks RFCOMM channels until none are left.
-     * Avoids reserved channels.
-     */
-    private static class RfcommChannelPicker {
-        private static final int[] RESERVED_RFCOMM_CHANNELS =  new int[] {
-            10,  // HFAG
-            11,  // HSAG
-            12,  // OPUSH
-            19,  // PBAP
-        };
-        private static LinkedList<Integer> sChannels;  // master list of non-reserved channels
-        private static Random sRandom;
-
-        private final LinkedList<Integer> mChannels;  // local list of channels left to try
-
-        private final UUID mUuid;
-
-        public RfcommChannelPicker(UUID uuid) {
-            synchronized (RfcommChannelPicker.class) {
-                if (sChannels == null) {
-                    // lazy initialization of non-reserved rfcomm channels
-                    sChannels = new LinkedList<Integer>();
-                    for (int i = 1; i <= BluetoothSocket.MAX_RFCOMM_CHANNEL; i++) {
-                        sChannels.addLast(new Integer(i));
-                    }
-                    for (int reserved : RESERVED_RFCOMM_CHANNELS) {
-                        sChannels.remove(new Integer(reserved));
-                    }
-                    sRandom = new Random();
-                }
-                mChannels = (LinkedList<Integer>)sChannels.clone();
-            }
-            mUuid = uuid;
-        }
-        /* Returns next random channel, or -1 if we're out */
-        public int nextChannel() {
-            if (mChannels.size() == 0) {
-                return -1;
-            }
-            return mChannels.remove(sRandom.nextInt(mChannels.size()));
-        }
-    }
-
-    /**
      * Create a listening, secure RFCOMM Bluetooth socket.
      * <p>A remote device connecting to this socket will be authenticated and
      * communication on this socket will be encrypted.
@@ -892,10 +912,10 @@
                 BluetoothSocket.TYPE_RFCOMM, true, true, channel);
         int errno = socket.mSocket.bindListen();
         if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
         return socket;
     }
@@ -996,70 +1016,23 @@
         return createNewRfcommSocketAndRecord(name, uuid, false, true);
     }
 
+
     private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
             boolean auth, boolean encrypt) throws IOException {
-        RfcommChannelPicker picker = new RfcommChannelPicker(uuid);
-
         BluetoothServerSocket socket;
-        int channel;
-        int errno;
-        while (true) {
-            channel = picker.nextChannel();
-
-            if (channel == -1) {
-                throw new IOException("No available channels");
-            }
-
-            socket = new BluetoothServerSocket(
-                    BluetoothSocket.TYPE_RFCOMM, auth, encrypt, channel);
-            errno = socket.mSocket.bindListen();
-            if (errno == 0) {
-                if (DBG) Log.d(TAG, "listening on RFCOMM channel " + channel);
-                break;  // success
-            } else if (errno == BluetoothSocket.EADDRINUSE) {
-                if (DBG) Log.d(TAG, "RFCOMM channel " + channel + " in use");
-                try {
-                    socket.close();
-                } catch (IOException e) {}
-                continue;  // try another channel
-            } else {
-                try {
-                    socket.close();
-                } catch (IOException e) {}
-                socket.mSocket.throwErrnoNative(errno);  // Exception as a result of bindListen()
-            }
+        socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
+                        encrypt, new ParcelUuid(uuid));
+        socket.setServiceName(name);
+        int errno = socket.mSocket.bindListen();
+        if (errno != 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
-
-        int handle = -1;
-        try {
-            handle = mService.addRfcommServiceRecord(name, new ParcelUuid(uuid), channel,
-                    new Binder());
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
-        if (handle == -1) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            throw new IOException("Not able to register SDP record for " + name);
-        }
-
-        if (mServiceRecordHandler == null) {
-            mServiceRecordHandler = new Handler(Looper.getMainLooper()) {
-                    public void handleMessage(Message msg) {
-                        /* handle socket closing */
-                        int handle = msg.what;
-                        try {
-                            if (DBG) Log.d(TAG, "Removing service record " +
-                                           Integer.toHexString(handle));
-                            mService.removeServiceRecord(handle);
-                        } catch (RemoteException e) {Log.e(TAG, "", e);}
-                    }
-                };
-        }
-        socket.setCloseHandler(mServiceRecordHandler, handle);
         return socket;
     }
 
-
     /**
      * Construct an unencrypted, unauthenticated, RFCOMM server socket.
      * Call #accept to retrieve connections to this socket.
@@ -1073,10 +1046,10 @@
                 BluetoothSocket.TYPE_RFCOMM, false, false, port);
         int errno = socket.mSocket.bindListen();
         if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
         return socket;
     }
@@ -1094,11 +1067,11 @@
         BluetoothServerSocket socket = new BluetoothServerSocket(
                 BluetoothSocket.TYPE_RFCOMM, false, true, port);
         int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+        if (errno < 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
         return socket;
     }
@@ -1115,11 +1088,10 @@
         BluetoothServerSocket socket = new BluetoothServerSocket(
                 BluetoothSocket.TYPE_SCO, false, false, -1);
         int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+        if (errno < 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
         }
         return socket;
     }
@@ -1134,6 +1106,8 @@
      */
     public Pair<byte[], byte[]> readOutOfBandData() {
         if (getState() != STATE_ON) return null;
+        //TODO(BT
+        /*
         try {
             byte[] hash;
             byte[] randomizer;
@@ -1151,7 +1125,7 @@
             }
             return new Pair<byte[], byte[]>(hash, randomizer);
 
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return null;
     }
 
@@ -1231,6 +1205,41 @@
         }
     }
 
+    final private IBluetoothManagerCallback mManagerCallback =
+        new IBluetoothManagerCallback.Stub() {
+            public void onBluetoothServiceUp(IBluetooth bluetoothService) {
+                if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
+                synchronized (mManagerCallback) {
+                    mService = bluetoothService;
+                    for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
+                        try {
+                            if (cb != null) {
+                                cb.onBluetoothServiceUp(bluetoothService);
+                            } else {
+                                Log.d(TAG, "onBluetoothServiceUp: cb is null!!!");
+                            }
+                        } catch (Exception e)  { Log.e(TAG,"",e);}
+                    }
+                }
+            }
+
+            public void onBluetoothServiceDown() {
+                if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
+                synchronized (mManagerCallback) {
+                    mService = null;
+                    for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
+                        try {
+                            if (cb != null) {
+                                cb.onBluetoothServiceDown();
+                            } else {
+                                Log.d(TAG, "onBluetoothServiceDown: cb is null!!!");
+                            }
+                        } catch (Exception e)  { Log.e(TAG,"",e);}
+                    }
+                }
+            }
+    };
+
     /**
      * Enable the Bluetooth Adapter, but don't auto-connect devices
      * and don't persist state. Only for use by system applications.
@@ -1276,12 +1285,14 @@
                                                    BluetoothStateChangeCallback callback) {
         if (callback == null) return false;
 
+        //TODO(BT)
+        /*
         try {
             return mService.changeApplicationBluetoothState(on, new
                     StateChangeCallbackWrapper(callback), new Binder());
         } catch (RemoteException e) {
             Log.e(TAG, "changeBluetoothState", e);
-        }
+        }*/
         return false;
     }
 
@@ -1309,14 +1320,22 @@
         }
     }
 
-    private Set<BluetoothDevice> toDeviceSet(String[] addresses) {
-        Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length);
-        for (int i = 0; i < addresses.length; i++) {
-            devices.add(getRemoteDevice(addresses[i]));
-        }
-        return Collections.unmodifiableSet(devices);
+    private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
+        Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
+        return Collections.unmodifiableSet(deviceSet);
     }
 
+    protected void finalize() throws Throwable {
+        try {
+            mManagerService.unregisterAdapter(mManagerCallback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        } finally {
+            super.finalize();
+        }
+    }
+
+
     /**
      * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
      * <p>Alphabetic characters must be uppercase to be valid.
@@ -1347,4 +1366,27 @@
         }
         return true;
     }
+
+    /*package*/ IBluetoothManager getBluetoothManager() {
+            return mManagerService;
+    }
+
+    private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>();
+
+    /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
+        synchronized (mManagerCallback) {
+            if (cb == null) {
+                Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
+            } else if (!mProxyServiceStateCallbacks.contains(cb)) {
+                mProxyServiceStateCallbacks.add(cb);
+            }
+        }
+        return mService;
+    }
+
+    /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
+        synchronized (mManagerCallback) {
+            mProxyServiceStateCallbacks.remove(cb);
+        }
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothAudioGateway.java b/core/java/android/bluetooth/BluetoothAudioGateway.java
deleted file mode 100644
index 9351393..0000000
--- a/core/java/android/bluetooth/BluetoothAudioGateway.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import java.lang.Thread;
-
-import android.os.Message;
-import android.os.Handler;
-import android.util.Log;
-
-/**
- * Listens for incoming RFCOMM connection for the headset / handsfree service.
- *
- * TODO: Use the new generic BluetoothSocket class instead of this legacy code
- *
- * @hide
- */
-public final class BluetoothAudioGateway {
-    private static final String TAG = "BT Audio Gateway";
-    private static final boolean DBG = false;
-
-    private int mNativeData;
-    static { classInitNative(); }
-
-    /* in */
-    private int mHandsfreeAgRfcommChannel = -1;
-    private int mHeadsetAgRfcommChannel   = -1;
-
-    /* out - written by native code */
-    private String mConnectingHeadsetAddress;
-    private int mConnectingHeadsetRfcommChannel; /* -1 when not connected */
-    private int mConnectingHeadsetSocketFd;
-    private String mConnectingHandsfreeAddress;
-    private int mConnectingHandsfreeRfcommChannel; /* -1 when not connected */
-    private int mConnectingHandsfreeSocketFd;
-    private int mTimeoutRemainingMs; /* in/out */
-
-    private final BluetoothAdapter mAdapter;
-
-    public static final int DEFAULT_HF_AG_CHANNEL = 10;
-    public static final int DEFAULT_HS_AG_CHANNEL = 11;
-
-    public BluetoothAudioGateway(BluetoothAdapter adapter) {
-        this(adapter, DEFAULT_HF_AG_CHANNEL, DEFAULT_HS_AG_CHANNEL);
-    }
-
-    public BluetoothAudioGateway(BluetoothAdapter adapter, int handsfreeAgRfcommChannel,
-                int headsetAgRfcommChannel) {
-        mAdapter = adapter;
-        mHandsfreeAgRfcommChannel = handsfreeAgRfcommChannel;
-        mHeadsetAgRfcommChannel = headsetAgRfcommChannel;
-        initializeNativeDataNative();
-    }
-
-    private Thread mConnectThead;
-    private volatile boolean mInterrupted;
-    private static final int SELECT_WAIT_TIMEOUT = 1000;
-
-    private Handler mCallback;
-
-    public class IncomingConnectionInfo {
-        public BluetoothAdapter mAdapter;
-        public BluetoothDevice mRemoteDevice;
-        public int mSocketFd;
-        public int mRfcommChan;
-        IncomingConnectionInfo(BluetoothAdapter adapter, BluetoothDevice remoteDevice,
-                int socketFd, int rfcommChan) {
-            mAdapter = adapter;
-            mRemoteDevice = remoteDevice;
-            mSocketFd = socketFd;
-            mRfcommChan = rfcommChan;
-        }
-    }
-
-    public static final int MSG_INCOMING_HEADSET_CONNECTION   = 100;
-    public static final int MSG_INCOMING_HANDSFREE_CONNECTION = 101;
-
-    public synchronized boolean start(Handler callback) {
-
-        if (mConnectThead == null) {
-            mCallback = callback;
-            mConnectThead = new Thread(TAG) {
-                    public void run() {
-                        if (DBG) log("Connect Thread starting");
-                        while (!mInterrupted) {
-                            //Log.i(TAG, "waiting for connect");
-                            mConnectingHeadsetRfcommChannel = -1;
-                            mConnectingHandsfreeRfcommChannel = -1;
-                            if (waitForHandsfreeConnectNative(SELECT_WAIT_TIMEOUT) == false) {
-                                if (mTimeoutRemainingMs > 0) {
-                                    try {
-                                        Log.i(TAG, "select thread timed out, but " + 
-                                              mTimeoutRemainingMs + "ms of waiting remain.");
-                                        Thread.sleep(mTimeoutRemainingMs);
-                                    } catch (InterruptedException e) {
-                                        Log.i(TAG, "select thread was interrupted (2), exiting");
-                                        mInterrupted = true;
-                                    }
-                                }
-                            }
-                            else {
-                                Log.i(TAG, "connect notification!");
-                                /* A device connected (most likely just one, but 
-                                   it is possible for two separate devices, one 
-                                   a headset and one a handsfree, to connect
-                                   simultaneously. 
-                                */
-                                if (mConnectingHeadsetRfcommChannel >= 0) {
-                                    Log.i(TAG, "Incoming connection from headset " + 
-                                          mConnectingHeadsetAddress + " on channel " + 
-                                          mConnectingHeadsetRfcommChannel);
-                                    Message msg = Message.obtain(mCallback);
-                                    msg.what = MSG_INCOMING_HEADSET_CONNECTION;
-                                    msg.obj = new IncomingConnectionInfo(
-                                        mAdapter,
-                                        mAdapter.getRemoteDevice(mConnectingHeadsetAddress),
-                                        mConnectingHeadsetSocketFd,
-                                        mConnectingHeadsetRfcommChannel);
-                                    msg.sendToTarget();
-                                }
-                                if (mConnectingHandsfreeRfcommChannel >= 0) {
-                                    Log.i(TAG, "Incoming connection from handsfree " + 
-                                          mConnectingHandsfreeAddress + " on channel " + 
-                                          mConnectingHandsfreeRfcommChannel);
-                                    Message msg = Message.obtain();
-                                    msg.setTarget(mCallback);
-                                    msg.what = MSG_INCOMING_HANDSFREE_CONNECTION;
-                                    msg.obj = new IncomingConnectionInfo(
-                                        mAdapter,
-                                        mAdapter.getRemoteDevice(mConnectingHandsfreeAddress),
-                                        mConnectingHandsfreeSocketFd,
-                                        mConnectingHandsfreeRfcommChannel);
-                                    msg.sendToTarget();
-                                }
-                            }
-                        }
-                        if (DBG) log("Connect Thread finished");
-                    }
-                };
-
-            if (setUpListeningSocketsNative() == false) {
-                Log.e(TAG, "Could not set up listening socket, exiting");
-                return false;
-            }
-
-            mInterrupted = false;
-            mConnectThead.start();
-        }
-
-        return true;
-    }
-
-    public synchronized void stop() {
-        if (mConnectThead != null) {
-            if (DBG) log("stopping Connect Thread");
-            mInterrupted = true;
-            try {
-                mConnectThead.interrupt();
-                if (DBG) log("waiting for thread to terminate");
-                mConnectThead.join();
-                mConnectThead = null;
-                mCallback = null;
-                tearDownListeningSocketsNative();
-            } catch (InterruptedException e) {
-                Log.w(TAG, "Interrupted waiting for Connect Thread to join");
-            }
-        }
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNativeDataNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private static native void classInitNative();
-    private native void initializeNativeDataNative();
-    private native void cleanupNativeDataNative();
-    private native boolean waitForHandsfreeConnectNative(int timeoutMs);
-    private native boolean setUpListeningSocketsNative();
-    private native void tearDownListeningSocketsNative();
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
old mode 100644
new mode 100755
index 56e1735..2504763
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -65,6 +65,7 @@
  */
 public final class BluetoothDevice implements Parcelable {
     private static final String TAG = "BluetoothDevice";
+    private static final boolean DBG = false;
 
     /**
      * Sentinel error value for this class. Guaranteed to not equal any other
@@ -483,16 +484,29 @@
     /*package*/ static IBluetooth getService() {
         synchronized (BluetoothDevice.class) {
             if (sService == null) {
-                IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
-                if (b == null) {
-                    throw new RuntimeException("Bluetooth service not available");
-                }
-                sService = IBluetooth.Stub.asInterface(b);
+                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+                sService = adapter.getBluetoothService(mStateChangeCallback);
             }
         }
         return sService;
     }
 
+    static IBluetoothManagerCallback mStateChangeCallback = new IBluetoothManagerCallback.Stub() {
+
+        public void onBluetoothServiceUp(IBluetooth bluetoothService)
+                throws RemoteException {
+            synchronized (BluetoothDevice.class) {
+                sService = bluetoothService;
+            }
+        }
+
+        public void onBluetoothServiceDown()
+            throws RemoteException {
+            synchronized (BluetoothDevice.class) {
+                sService = null;
+            }
+        }
+    };
     /**
      * Create a new BluetoothDevice
      * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
@@ -561,6 +575,7 @@
      * @return Bluetooth hardware address as string
      */
     public String getAddress() {
+        if (DBG) Log.d(TAG, "mAddress: " + mAddress);
         return mAddress;
     }
 
@@ -575,8 +590,12 @@
      * @return the Bluetooth name, or null if there was a problem.
      */
     public String getName() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
+            return null;
+        }
         try {
-            return sService.getRemoteName(mAddress);
+            return sService.getRemoteName(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -589,8 +608,12 @@
      * @hide
      */
     public String getAlias() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
+            return null;
+        }
         try {
-            return sService.getRemoteAlias(mAddress);
+            return sService.getRemoteAlias(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -606,8 +629,12 @@
      * @hide
      */
     public boolean setAlias(String alias) {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
+            return false;
+        }
         try {
-            return sService.setRemoteAlias(mAddress, alias);
+            return sService.setRemoteAlias(this, alias);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -642,8 +669,12 @@
      * @hide
      */
     public boolean createBond() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
+            return false;
+        }
         try {
-            return sService.createBond(mAddress);
+            return sService.createBond(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -668,9 +699,11 @@
      * @hide
      */
     public boolean createBondOutOfBand(byte[] hash, byte[] randomizer) {
+        //TODO(BT)
+        /*
         try {
-            return sService.createBondOutOfBand(mAddress, hash, randomizer);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return sService.createBondOutOfBand(this, hash, randomizer);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return false;
     }
 
@@ -688,9 +721,11 @@
      * @hide
      */
     public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) {
+      //TODO(BT)
+      /*
       try {
-        return sService.setDeviceOutOfBandData(mAddress, hash, randomizer);
-      } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return sService.setDeviceOutOfBandData(this, hash, randomizer);
+      } catch (RemoteException e) {Log.e(TAG, "", e);} */
       return false;
     }
 
@@ -702,8 +737,12 @@
      * @hide
      */
     public boolean cancelBondProcess() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
+            return false;
+        }
         try {
-            return sService.cancelBondProcess(mAddress);
+            return sService.cancelBondProcess(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -719,8 +758,12 @@
      * @hide
      */
     public boolean removeBond() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
+            return false;
+        }
         try {
-            return sService.removeBond(mAddress);
+            return sService.removeBond(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -736,8 +779,12 @@
      * @return the bond state
      */
     public int getBondState() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get bond state");
+            return BOND_NONE;
+        }
         try {
-            return sService.getBondState(mAddress);
+            return sService.getBondState(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return BOND_NONE;
     }
@@ -749,8 +796,12 @@
      * @return Bluetooth class object, or null on error
      */
     public BluetoothClass getBluetoothClass() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
+            return null;
+        }
         try {
-            int classInt = sService.getRemoteClass(mAddress);
+            int classInt = sService.getRemoteClass(this);
             if (classInt == BluetoothClass.ERROR) return null;
             return new BluetoothClass(classInt);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -763,11 +814,13 @@
      * @hide
      */
     public boolean getTrustState() {
+        //TODO(BT)
+        /*
         try {
-            return sService.getTrustState(mAddress);
+            return sService.getTrustState(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
-        }
+        }*/
         return false;
     }
 
@@ -778,11 +831,13 @@
      * @hide
      */
     public boolean setTrust(boolean value) {
+        //TODO(BT)
+        /*
         try {
-            return sService.setTrust(mAddress, value);
+            return sService.setTrust(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
-        }
+        }*/
         return false;
     }
 
@@ -799,8 +854,12 @@
      *         or null on error
      */
      public ParcelUuid[] getUuids() {
+         if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
+             return null;
+         }
         try {
-            return sService.getRemoteUuids(mAddress);
+            return sService.getRemoteUuids(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -822,64 +881,84 @@
       */
      public boolean fetchUuidsWithSdp() {
         try {
-            return sService.fetchRemoteUuids(mAddress, null, null);
+            return sService.fetchRemoteUuids(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
-        return false;
+            return false;
     }
 
     /** @hide */
     public int getServiceChannel(ParcelUuid uuid) {
+        //TODO(BT)
+        /*
          try {
-             return sService.getRemoteServiceChannel(mAddress, uuid);
-         } catch (RemoteException e) {Log.e(TAG, "", e);}
+             return sService.getRemoteServiceChannel(this, uuid);
+         } catch (RemoteException e) {Log.e(TAG, "", e);}*/
          return BluetoothDevice.ERROR;
     }
 
     /** @hide */
     public boolean setPin(byte[] pin) {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
+            return false;
+        }
         try {
-            return sService.setPin(mAddress, pin);
+            return sService.setPin(this, true, pin.length, pin);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
     public boolean setPasskey(int passkey) {
+        //TODO(BT)
+        /*
         try {
-            return sService.setPasskey(mAddress, passkey);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return sService.setPasskey(this, true, 4, passkey);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return false;
     }
 
     /** @hide */
     public boolean setPairingConfirmation(boolean confirm) {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
+            return false;
+        }
         try {
-            return sService.setPairingConfirmation(mAddress, confirm);
+            return sService.setPairingConfirmation(this, confirm);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
     public boolean setRemoteOutOfBandData() {
+        // TODO(BT)
+        /*
         try {
-          return sService.setRemoteOutOfBandData(mAddress);
-      } catch (RemoteException e) {Log.e(TAG, "", e);}
+          return sService.setRemoteOutOfBandData(this);
+      } catch (RemoteException e) {Log.e(TAG, "", e);}*/
       return false;
     }
 
     /** @hide */
     public boolean cancelPairingUserInput() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot create pairing user input");
+            return false;
+        }
         try {
-            return sService.cancelPairingUserInput(mAddress);
+            return sService.cancelBondProcess(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
     public boolean isBluetoothDock() {
+        // TODO(BT)
+        /*
         try {
-            return sService.isBluetoothDock(mAddress);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return sService.isBluetoothDock(this);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return false;
     }
 
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
deleted file mode 100644
index 020f051..0000000
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ /dev/null
@@ -1,1357 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Message;
-import android.bluetooth.BluetoothAdapter;
-import android.os.PowerManager;
-import android.server.BluetoothA2dpService;
-import android.server.BluetoothService;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.util.Set;
-
-/**
- * This class is the Profile connection state machine associated with a remote
- * device. When the device bonds an instance of this class is created.
- * This tracks incoming and outgoing connections of all the profiles. Incoming
- * connections are preferred over outgoing connections and HFP preferred over
- * A2DP. When the device is unbonded, the instance is removed.
- *
- * States:
- * {@link BondedDevice}: This state represents a bonded device. When in this
- * state none of the profiles are in transition states.
- *
- * {@link OutgoingHandsfree}: Handsfree profile connection is in a transition
- * state because of a outgoing Connect or Disconnect.
- *
- * {@link IncomingHandsfree}: Handsfree profile connection is in a transition
- * state because of a incoming Connect or Disconnect.
- *
- * {@link IncomingA2dp}: A2dp profile connection is in a transition
- * state because of a incoming Connect or Disconnect.
- *
- * {@link OutgoingA2dp}: A2dp profile connection is in a transition
- * state because of a outgoing Connect or Disconnect.
- *
- * Todo(): Write tests for this class, when the Android Mock support is completed.
- * @hide
- */
-public final class BluetoothDeviceProfileState extends StateMachine {
-    private static final String TAG = "BluetoothDeviceProfileState";
-    private static final boolean DBG = false;
-
-    // TODO(): Restructure the state machine to make it scalable with regard to profiles.
-    public static final int CONNECT_HFP_OUTGOING = 1;
-    public static final int CONNECT_HFP_INCOMING = 2;
-    public static final int CONNECT_A2DP_OUTGOING = 3;
-    public static final int CONNECT_A2DP_INCOMING = 4;
-    public static final int CONNECT_HID_OUTGOING = 5;
-    public static final int CONNECT_HID_INCOMING = 6;
-
-    public static final int DISCONNECT_HFP_OUTGOING = 50;
-    private static final int DISCONNECT_HFP_INCOMING = 51;
-    public static final int DISCONNECT_A2DP_OUTGOING = 52;
-    public static final int DISCONNECT_A2DP_INCOMING = 53;
-    public static final int DISCONNECT_HID_OUTGOING = 54;
-    public static final int DISCONNECT_HID_INCOMING = 55;
-    public static final int DISCONNECT_PBAP_OUTGOING = 56;
-
-    public static final int UNPAIR = 100;
-    public static final int AUTO_CONNECT_PROFILES = 101;
-    public static final int TRANSITION_TO_STABLE = 102;
-    public static final int CONNECT_OTHER_PROFILES = 103;
-    private static final int CONNECTION_ACCESS_REQUEST_REPLY = 104;
-    private static final int CONNECTION_ACCESS_REQUEST_EXPIRY = 105;
-
-    public static final int CONNECT_OTHER_PROFILES_DELAY = 4000; // 4 secs
-    private static final int CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT = 7000; // 7 secs
-    private static final int CONNECTION_ACCESS_UNDEFINED = -1;
-    private static final long INIT_INCOMING_REJECT_TIMER = 1000; // 1 sec
-    private static final long MAX_INCOMING_REJECT_TIMER = 3600 * 1000 * 4; // 4 hours
-
-    private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings";
-    private static final String ACCESS_AUTHORITY_CLASS =
-        "com.android.settings.bluetooth.BluetoothPermissionRequest";
-
-    private BondedDevice mBondedDevice = new BondedDevice();
-    private OutgoingHandsfree mOutgoingHandsfree = new OutgoingHandsfree();
-    private IncomingHandsfree mIncomingHandsfree = new IncomingHandsfree();
-    private IncomingA2dp mIncomingA2dp = new IncomingA2dp();
-    private OutgoingA2dp mOutgoingA2dp = new OutgoingA2dp();
-    private OutgoingHid mOutgoingHid = new OutgoingHid();
-    private IncomingHid mIncomingHid = new IncomingHid();
-
-    private Context mContext;
-    private BluetoothService mService;
-    private BluetoothA2dpService mA2dpService;
-    private BluetoothHeadset  mHeadsetService;
-    private BluetoothPbap     mPbapService;
-    private PbapServiceListener mPbap;
-    private BluetoothAdapter mAdapter;
-    private boolean mPbapServiceConnected;
-    private boolean mAutoConnectionPending;
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-
-    private BluetoothDevice mDevice;
-    private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
-    private int mA2dpState = BluetoothProfile.STATE_DISCONNECTED;
-    private long mIncomingRejectTimer;
-    private boolean mConnectionAccessReplyReceived = false;
-    private Pair<Integer, String> mIncomingConnections;
-    private PowerManager.WakeLock mWakeLock;
-    private PowerManager mPowerManager;
-    private boolean mPairingRequestRcvd = false;
-
-    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (device == null || !device.equals(mDevice)) return;
-
-            if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-                // We trust this device now
-                if (newState == BluetoothHeadset.STATE_CONNECTED) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                }
-                mA2dpState = newState;
-                if (oldState == BluetoothA2dp.STATE_CONNECTED &&
-                    newState == BluetoothA2dp.STATE_DISCONNECTED) {
-                    sendMessage(DISCONNECT_A2DP_INCOMING);
-                }
-                if (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-                // We trust this device now
-                if (newState == BluetoothHeadset.STATE_CONNECTED) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                }
-                mHeadsetState = newState;
-                if (oldState == BluetoothHeadset.STATE_CONNECTED &&
-                    newState == BluetoothHeadset.STATE_DISCONNECTED) {
-                    sendMessage(DISCONNECT_HFP_INCOMING);
-                }
-                if (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                int oldState =
-                    intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-                // We trust this device now
-                if (newState == BluetoothHeadset.STATE_CONNECTED) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                }
-                if (oldState == BluetoothProfile.STATE_CONNECTED &&
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(DISCONNECT_HID_INCOMING);
-                }
-                if (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
-                // This is technically not needed, but we can get stuck sometimes.
-                // For example, if incoming A2DP fails, we are not informed by Bluez
-                sendMessage(TRANSITION_TO_STABLE);
-            } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) {
-                mWakeLock.release();
-                int val = intent.getIntExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
-                                             BluetoothDevice.CONNECTION_ACCESS_NO);
-                Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_REPLY);
-                msg.arg1 = val;
-                sendMessage(msg);
-            } else if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
-                mPairingRequestRcvd = true;
-            } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
-                        BluetoothDevice.ERROR);
-                if (state == BluetoothDevice.BOND_BONDED && mPairingRequestRcvd) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                    mPairingRequestRcvd = false;
-                } else if (state == BluetoothDevice.BOND_NONE) {
-                    mPairingRequestRcvd = false;
-                }
-            }
-        }
-    };
-
-    private boolean isPhoneDocked(BluetoothDevice autoConnectDevice) {
-        // This works only because these broadcast intents are "sticky"
-        Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
-        if (i != null) {
-            int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                if (device != null && autoConnectDevice.equals(device)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public BluetoothDeviceProfileState(Context context, String address,
-          BluetoothService service, BluetoothA2dpService a2dpService, boolean setTrust) {
-        super(address);
-        mContext = context;
-        mDevice = new BluetoothDevice(address);
-        mService = service;
-        mA2dpService = a2dpService;
-
-        addState(mBondedDevice);
-        addState(mOutgoingHandsfree);
-        addState(mIncomingHandsfree);
-        addState(mIncomingA2dp);
-        addState(mOutgoingA2dp);
-        addState(mOutgoingHid);
-        addState(mIncomingHid);
-        setInitialState(mBondedDevice);
-
-        IntentFilter filter = new IntentFilter();
-        // Fine-grained state broadcasts
-        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
-        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
-        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
-
-        mContext.registerReceiver(mBroadcastReceiver, filter);
-
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
-                                BluetoothProfile.HEADSET);
-        // TODO(): Convert PBAP to the new Profile APIs.
-        mPbap = new PbapServiceListener();
-
-        mIncomingConnections = mService.getIncomingState(address);
-        mIncomingRejectTimer = readTimerValue();
-        mPowerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
-                                              PowerManager.ACQUIRE_CAUSES_WAKEUP |
-                                              PowerManager.ON_AFTER_RELEASE, TAG);
-        mWakeLock.setReferenceCounted(false);
-
-        if (setTrust) {
-            setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-        }
-    }
-
-    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mHeadsetService = (BluetoothHeadset) proxy;
-                if (mAutoConnectionPending) {
-                    sendMessage(AUTO_CONNECT_PROFILES);
-                    mAutoConnectionPending = false;
-                }
-            }
-        }
-        public void onServiceDisconnected(int profile) {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mHeadsetService = null;
-            }
-        }
-    };
-
-    private class PbapServiceListener implements BluetoothPbap.ServiceListener {
-        public PbapServiceListener() {
-            mPbapService = new BluetoothPbap(mContext, this);
-        }
-        public void onServiceConnected() {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mPbapServiceConnected = true;
-            }
-        }
-        public void onServiceDisconnected() {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mPbapServiceConnected = false;
-            }
-        }
-    }
-
-    @Override
-    protected void onQuitting() {
-        mContext.unregisterReceiver(mBroadcastReceiver);
-        mBroadcastReceiver = null;
-        mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService);
-        mBluetoothProfileServiceListener = null;
-        mOutgoingHandsfree = null;
-        mPbap = null;
-        mPbapService.close();
-        mPbapService = null;
-        mIncomingHid = null;
-        mOutgoingHid = null;
-        mIncomingHandsfree = null;
-        mOutgoingHandsfree = null;
-        mIncomingA2dp = null;
-        mOutgoingA2dp = null;
-        mBondedDevice = null;
-    }
-
-    private class BondedDevice extends State {
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering ACL Connected state with: " + getCurrentMessage().what);
-            Message m = new Message();
-            m.copyFrom(getCurrentMessage());
-            sendMessageAtFrontOfQueue(m);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("ACL Connected State -> Processing Message: " + message.what);
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                case DISCONNECT_HFP_OUTGOING:
-                    transitionTo(mOutgoingHandsfree);
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    transitionTo(mIncomingHandsfree);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    transitionTo(mIncomingHandsfree);
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                case DISCONNECT_A2DP_OUTGOING:
-                    transitionTo(mOutgoingA2dp);
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                case DISCONNECT_A2DP_INCOMING:
-                    transitionTo(mIncomingA2dp);
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    transitionTo(mOutgoingHid);
-                    break;
-                case CONNECT_HID_INCOMING:
-                case DISCONNECT_HID_INCOMING:
-                    transitionTo(mIncomingHid);
-                    break;
-                case DISCONNECT_PBAP_OUTGOING:
-                    processCommand(DISCONNECT_PBAP_OUTGOING);
-                    break;
-                case UNPAIR:
-                    if (mHeadsetState != BluetoothHeadset.STATE_DISCONNECTED) {
-                        sendMessage(DISCONNECT_HFP_OUTGOING);
-                        deferMessage(message);
-                        break;
-                    } else if (mA2dpState != BluetoothA2dp.STATE_DISCONNECTED) {
-                        sendMessage(DISCONNECT_A2DP_OUTGOING);
-                        deferMessage(message);
-                        break;
-                    } else if (mService.getInputDeviceConnectionState(mDevice) !=
-                            BluetoothInputDevice.STATE_DISCONNECTED) {
-                        sendMessage(DISCONNECT_HID_OUTGOING);
-                        deferMessage(message);
-                        break;
-                    }
-                    processCommand(UNPAIR);
-                    break;
-                case AUTO_CONNECT_PROFILES:
-                    if (isPhoneDocked(mDevice)) {
-                        // Don't auto connect to docks.
-                        break;
-                    } else {
-                        if (mHeadsetService == null) {
-                              mAutoConnectionPending = true;
-                        } else if (mHeadsetService.getPriority(mDevice) ==
-                              BluetoothHeadset.PRIORITY_AUTO_CONNECT &&
-                              mHeadsetService.getDevicesMatchingConnectionStates(
-                                  new int[] {BluetoothProfile.STATE_CONNECTED,
-                                             BluetoothProfile.STATE_CONNECTING,
-                                             BluetoothProfile.STATE_DISCONNECTING}).size() == 0) {
-                            mHeadsetService.connect(mDevice);
-                        }
-                        if (mA2dpService != null &&
-                              mA2dpService.getPriority(mDevice) ==
-                              BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
-                              mA2dpService.getDevicesMatchingConnectionStates(
-                                  new int[] {BluetoothA2dp.STATE_CONNECTED,
-                                             BluetoothProfile.STATE_CONNECTING,
-                                             BluetoothProfile.STATE_DISCONNECTING}).size() == 0) {
-                            mA2dpService.connect(mDevice);
-                        }
-                        if (mService.getInputDevicePriority(mDevice) ==
-                              BluetoothInputDevice.PRIORITY_AUTO_CONNECT) {
-                            mService.connectInputDevice(mDevice);
-                        }
-                    }
-                    break;
-                case CONNECT_OTHER_PROFILES:
-                    if (isPhoneDocked(mDevice)) {
-                       break;
-                    }
-                    if (message.arg1 == CONNECT_A2DP_OUTGOING) {
-                        if (mA2dpService != null &&
-                            mA2dpService.getConnectedDevices().size() == 0) {
-                            Log.i(TAG, "A2dp:Connect Other Profiles");
-                            mA2dpService.connect(mDevice);
-                        }
-                    } else if (message.arg1 == CONNECT_HFP_OUTGOING) {
-                        if (mHeadsetService == null) {
-                            deferMessage(message);
-                        } else {
-                            if (mHeadsetService.getConnectedDevices().size() == 0) {
-                                Log.i(TAG, "Headset:Connect Other Profiles");
-                                mHeadsetService.connect(mDevice);
-                            }
-                        }
-                    }
-                    break;
-                case TRANSITION_TO_STABLE:
-                    // ignore.
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class OutgoingHandsfree extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering OutgoingHandsfree state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_HFP_OUTGOING &&
-                mCommand != DISCONNECT_HFP_OUTGOING) {
-                Log.e(TAG, "Error: OutgoingHandsfree state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.HFP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("OutgoingHandsfree State -> Processing Message: " + message.what);
-            Message deferMsg = new Message();
-            int command = message.what;
-            switch(command) {
-                case CONNECT_HFP_OUTGOING:
-                    if (command != mCommand) {
-                        // Disconnect followed by a connect - defer
-                        deferMessage(message);
-                    }
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    if (mCommand == CONNECT_HFP_OUTGOING) {
-                        // Cancel outgoing connect, accept incoming
-                        cancelCommand(CONNECT_HFP_OUTGOING);
-                        transitionTo(mIncomingHandsfree);
-                    } else {
-                        // We have done the disconnect but we are not
-                        // sure which state we are in at this point.
-                        deferMessage(message);
-                    }
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // accept incoming A2DP, retry HFP_OUTGOING
-                    transitionTo(mIncomingA2dp);
-
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    if (mCommand == CONNECT_HFP_OUTGOING) {
-                        // Cancel outgoing connect
-                        cancelCommand(CONNECT_HFP_OUTGOING);
-                        processCommand(DISCONNECT_HFP_OUTGOING);
-                    }
-                    // else ignore
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // When this happens the socket would be closed and the headset
-                    // state moved to DISCONNECTED, cancel the outgoing thread.
-                    // if it still is in CONNECTING state
-                    cancelCommand(CONNECT_HFP_OUTGOING);
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Bluez will handle the disconnect. If because of this the outgoing
-                    // handsfree connection has failed, then retry.
-                    if (mStatus) {
-                       deferMsg.what = mCommand;
-                       deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                    transitionTo(mIncomingHid);
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_HID_INCOMING:
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class IncomingHandsfree extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering IncomingHandsfree state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_HFP_INCOMING &&
-                mCommand != DISCONNECT_HFP_INCOMING) {
-                Log.e(TAG, "Error: IncomingHandsfree state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.HFP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("IncomingHandsfree State -> Processing Message: " + message.what);
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    // Ignore
-                    Log.e(TAG, "Error: Incoming connection with a pending incoming connection");
-                    break;
-                case CONNECTION_ACCESS_REQUEST_REPLY:
-                    int val = message.arg1;
-                    mConnectionAccessReplyReceived = true;
-                    boolean value = false;
-                    if (val == BluetoothDevice.CONNECTION_ACCESS_YES) {
-                        value = true;
-                    }
-                    setTrust(val);
-
-                    handleIncomingConnection(CONNECT_HFP_INCOMING, value);
-                    break;
-                case CONNECTION_ACCESS_REQUEST_EXPIRY:
-                    if (!mConnectionAccessReplyReceived) {
-                        handleIncomingConnection(CONNECT_HFP_INCOMING, false);
-                        sendConnectionAccessRemovalIntent();
-                        sendMessage(TRANSITION_TO_STABLE);
-                    }
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // Serialize the commands.
-                    deferMessage(message);
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    // We don't know at what state we are in the incoming HFP connection state.
-                    // We can be changing from DISCONNECTED to CONNECTING, or
-                    // from CONNECTING to CONNECTED, so serializing this command is
-                    // the safest option.
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // Nothing to do here, we will already be DISCONNECTED
-                    // by this point.
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Bluez handles incoming A2DP disconnect.
-                    // If this causes incoming HFP to fail, it is more of a headset problem
-                    // since both connections are incoming ones.
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                case DISCONNECT_HID_INCOMING:
-                     break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class OutgoingA2dp extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering OutgoingA2dp state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_A2DP_OUTGOING &&
-                mCommand != DISCONNECT_A2DP_OUTGOING) {
-                Log.e(TAG, "Error: OutgoingA2DP state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.A2DP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("OutgoingA2dp State->Processing Message: " + message.what);
-            Message deferMsg = new Message();
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                    processCommand(CONNECT_HFP_OUTGOING);
-
-                    // Don't cancel A2DP outgoing as there is no guarantee it
-                    // will get canceled.
-                    // It might already be connected but we might not have got the
-                    // A2DP_SINK_STATE_CHANGE. Hence, no point disconnecting here.
-                    // The worst case, the connection will fail, retry.
-                    // The same applies to Disconnecting an A2DP connection.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    processCommand(CONNECT_HFP_INCOMING);
-
-                    // Don't cancel A2DP outgoing as there is no guarantee
-                    // it will get canceled.
-                    // The worst case, the connection will fail, retry.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // Bluez will take care of conflicts between incoming and outgoing
-                    // connections.
-                    transitionTo(mIncomingA2dp);
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    // Ignore
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // At this point, we are already disconnected
-                    // with HFP. Sometimes A2DP connection can
-                    // fail due to the disconnection of HFP. So add a retry
-                    // for the A2DP.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Ignore, will be handled by Bluez
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                    transitionTo(mIncomingHid);
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_HID_INCOMING:
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class IncomingA2dp extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering IncomingA2dp state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_A2DP_INCOMING &&
-                mCommand != DISCONNECT_A2DP_INCOMING) {
-                Log.e(TAG, "Error: IncomingA2DP state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.A2DP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("IncomingA2dp State->Processing Message: " + message.what);
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    // Shouldn't happen, but serialize the commands.
-                    deferMessage(message);
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // ignore
-                    break;
-                case CONNECTION_ACCESS_REQUEST_REPLY:
-                    int val = message.arg1;
-                    mConnectionAccessReplyReceived = true;
-                    boolean value = false;
-                    if (val == BluetoothDevice.CONNECTION_ACCESS_YES) {
-                        value = true;
-                    }
-                    setTrust(val);
-                    handleIncomingConnection(CONNECT_A2DP_INCOMING, value);
-                    break;
-                case CONNECTION_ACCESS_REQUEST_EXPIRY:
-                    // The check protects the race condition between REQUEST_REPLY
-                    // and the timer expiry.
-                    if (!mConnectionAccessReplyReceived) {
-                        handleIncomingConnection(CONNECT_A2DP_INCOMING, false);
-                        sendConnectionAccessRemovalIntent();
-                        sendMessage(TRANSITION_TO_STABLE);
-                    }
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    // Defer message and retry
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // Shouldn't happen but if does, we can handle it.
-                    // Depends if the headset can handle it.
-                    // Incoming A2DP will be handled by Bluez, Disconnect HFP
-                    // the socket would have already been closed.
-                    // ignore
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Ignore, will be handled by Bluez
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                case DISCONNECT_HID_INCOMING:
-                     break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-
-    private class OutgoingHid extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            log("Entering OutgoingHid state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_HID_OUTGOING &&
-                mCommand != DISCONNECT_HID_OUTGOING) {
-                Log.e(TAG, "Error: OutgoingHid state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("OutgoingHid State->Processing Message: " + message.what);
-            Message deferMsg = new Message();
-            switch(message.what) {
-                // defer all outgoing messages
-                case CONNECT_HFP_OUTGOING:
-                case CONNECT_A2DP_OUTGOING:
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HFP_OUTGOING:
-                case DISCONNECT_A2DP_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-
-                case CONNECT_HFP_INCOMING:
-                    transitionTo(mIncomingHandsfree);
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    transitionTo(mIncomingA2dp);
-
-                    // Don't cancel HID outgoing as there is no guarantee it
-                    // will get canceled.
-                    // It might already be connected but we might not have got the
-                    // INPUT_DEVICE_STATE_CHANGE. Hence, no point disconnecting here.
-                    // The worst case, the connection will fail, retry.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_HID_INCOMING:
-                  // Bluez will take care of the conflicts
-                    transitionTo(mIncomingHid);
-                    break;
-
-                case DISCONNECT_HFP_INCOMING:
-                case DISCONNECT_A2DP_INCOMING:
-                    // At this point, we are already disconnected
-                    // with HFP. Sometimes HID connection can
-                    // fail due to the disconnection of HFP. So add a retry
-                    // for the HID.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_HID_INCOMING:
-                    // Ignore, will be handled by Bluez
-                    break;
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-  private class IncomingHid extends State {
-      private boolean mStatus = false;
-      private int mCommand;
-
-      @Override
-    public void enter() {
-          log("Entering IncomingHid state with: " + getCurrentMessage().what);
-          mCommand = getCurrentMessage().what;
-          if (mCommand != CONNECT_HID_INCOMING &&
-              mCommand != DISCONNECT_HID_INCOMING) {
-              Log.e(TAG, "Error: IncomingHid state with command:" + mCommand);
-          }
-          mStatus = processCommand(mCommand);
-          if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
-      }
-
-      @Override
-    public boolean processMessage(Message message) {
-          log("IncomingHid State->Processing Message: " + message.what);
-          Message deferMsg = new Message();
-          switch(message.what) {
-              case CONNECT_HFP_OUTGOING:
-              case CONNECT_HFP_INCOMING:
-              case DISCONNECT_HFP_OUTGOING:
-              case CONNECT_A2DP_INCOMING:
-              case CONNECT_A2DP_OUTGOING:
-              case DISCONNECT_A2DP_OUTGOING:
-              case CONNECT_HID_OUTGOING:
-              case CONNECT_HID_INCOMING:
-              case DISCONNECT_HID_OUTGOING:
-                  deferMessage(message);
-                  break;
-              case CONNECTION_ACCESS_REQUEST_REPLY:
-                  mConnectionAccessReplyReceived = true;
-                  int val = message.arg1;
-                  setTrust(val);
-                  handleIncomingConnection(CONNECT_HID_INCOMING,
-                      val == BluetoothDevice.CONNECTION_ACCESS_YES);
-                  break;
-              case CONNECTION_ACCESS_REQUEST_EXPIRY:
-                  if (!mConnectionAccessReplyReceived) {
-                      handleIncomingConnection(CONNECT_HID_INCOMING, false);
-                      sendConnectionAccessRemovalIntent();
-                      sendMessage(TRANSITION_TO_STABLE);
-                  }
-                  break;
-              case DISCONNECT_HFP_INCOMING:
-                  // Shouldn't happen but if does, we can handle it.
-                  // Depends if the headset can handle it.
-                  // Incoming HID will be handled by Bluez, Disconnect HFP
-                  // the socket would have already been closed.
-                  // ignore
-                  break;
-              case DISCONNECT_HID_INCOMING:
-              case DISCONNECT_A2DP_INCOMING:
-                  // Ignore, will be handled by Bluez
-                  break;
-              case DISCONNECT_PBAP_OUTGOING:
-              case UNPAIR:
-              case AUTO_CONNECT_PROFILES:
-                  deferMessage(message);
-                  break;
-              case TRANSITION_TO_STABLE:
-                  transitionTo(mBondedDevice);
-                  break;
-              default:
-                  return NOT_HANDLED;
-          }
-          return HANDLED;
-      }
-  }
-
-
-    synchronized void cancelCommand(int command) {
-        if (command == CONNECT_HFP_OUTGOING ) {
-            // Cancel the outgoing thread.
-            if (mHeadsetService != null) {
-                mHeadsetService.cancelConnectThread();
-            }
-            // HeadsetService is down. Phone process most likely crashed.
-            // The thread would have got killed.
-        }
-    }
-
-    synchronized void deferProfileServiceMessage(int command) {
-        Message msg = new Message();
-        msg.what = command;
-        deferMessage(msg);
-    }
-
-    private void updateIncomingAllowedTimer() {
-        // Not doing a perfect exponential backoff because
-        // we want two different rates. For all practical
-        // purposes, this is good enough.
-        if (mIncomingRejectTimer == 0) mIncomingRejectTimer = INIT_INCOMING_REJECT_TIMER;
-
-        mIncomingRejectTimer *= 5;
-        if (mIncomingRejectTimer > MAX_INCOMING_REJECT_TIMER) {
-            mIncomingRejectTimer = MAX_INCOMING_REJECT_TIMER;
-        }
-        writeTimerValue(mIncomingRejectTimer);
-    }
-
-    private boolean handleIncomingConnection(int command, boolean accept) {
-        boolean ret = false;
-        Log.i(TAG, "handleIncomingConnection:" + command + ":" + accept);
-        switch (command) {
-            case CONNECT_HFP_INCOMING:
-                if (!accept) {
-                    ret = mHeadsetService.rejectIncomingConnect(mDevice);
-                    sendMessage(TRANSITION_TO_STABLE);
-                    updateIncomingAllowedTimer();
-                } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
-                    writeTimerValue(0);
-                    ret =  mHeadsetService.acceptIncomingConnect(mDevice);
-                } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
-                    writeTimerValue(0);
-                    handleConnectionOfOtherProfiles(command);
-                    ret = mHeadsetService.createIncomingConnect(mDevice);
-                }
-                break;
-            case CONNECT_A2DP_INCOMING:
-                if (!accept) {
-                    ret = mA2dpService.allowIncomingConnect(mDevice, false);
-                    sendMessage(TRANSITION_TO_STABLE);
-                    updateIncomingAllowedTimer();
-                } else {
-                    writeTimerValue(0);
-                    ret = mA2dpService.allowIncomingConnect(mDevice, true);
-                    handleConnectionOfOtherProfiles(command);
-                }
-                break;
-            case CONNECT_HID_INCOMING:
-                if (!accept) {
-                    ret = mService.allowIncomingProfileConnect(mDevice, false);
-                    sendMessage(TRANSITION_TO_STABLE);
-                    updateIncomingAllowedTimer();
-                } else {
-                    writeTimerValue(0);
-                    ret = mService.allowIncomingProfileConnect(mDevice, true);
-                }
-                break;
-            default:
-                Log.e(TAG, "Waiting for incoming connection but state changed to:" + command);
-                break;
-       }
-       return ret;
-    }
-
-    private void sendConnectionAccessIntent() {
-        mConnectionAccessReplyReceived = false;
-
-        if (!mPowerManager.isScreenOn()) mWakeLock.acquire();
-
-        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST);
-        intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
-        intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
-                        BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
-    private void sendConnectionAccessRemovalIntent() {
-        mWakeLock.release();
-        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
-    private int getTrust() {
-        String address = mDevice.getAddress();
-        if (mIncomingConnections != null) return mIncomingConnections.first;
-        return CONNECTION_ACCESS_UNDEFINED;
-    }
-
-
-    private String getStringValue(long value) {
-        StringBuilder sbr = new StringBuilder();
-        sbr.append(Long.toString(System.currentTimeMillis()));
-        sbr.append("-");
-        sbr.append(Long.toString(value));
-        return sbr.toString();
-    }
-
-    private void setTrust(int value) {
-        String second;
-        if (mIncomingConnections == null) {
-            second = getStringValue(INIT_INCOMING_REJECT_TIMER);
-        } else {
-            second = mIncomingConnections.second;
-        }
-
-        mIncomingConnections = new Pair(value, second);
-        mService.writeIncomingConnectionState(mDevice.getAddress(), mIncomingConnections);
-    }
-
-    private void writeTimerValue(long value) {
-        Integer first;
-        if (mIncomingConnections == null) {
-            first = CONNECTION_ACCESS_UNDEFINED;
-        } else {
-            first = mIncomingConnections.first;
-        }
-        mIncomingConnections = new Pair(first, getStringValue(value));
-        mService.writeIncomingConnectionState(mDevice.getAddress(), mIncomingConnections);
-    }
-
-    private long readTimerValue() {
-        if (mIncomingConnections == null)
-            return 0;
-        String value = mIncomingConnections.second;
-        String[] splits = value.split("-");
-        if (splits != null && splits.length == 2) {
-            return Long.parseLong(splits[1]);
-        }
-        return 0;
-    }
-
-    private boolean readIncomingAllowedValue() {
-        if (readTimerValue() == 0) return true;
-        String value = mIncomingConnections.second;
-        String[] splits = value.split("-");
-        if (splits != null && splits.length == 2) {
-            long val1 = Long.parseLong(splits[0]);
-            long val2 = Long.parseLong(splits[1]);
-            if (val1 + val2 <= System.currentTimeMillis()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    synchronized boolean processCommand(int command) {
-        log("Processing command:" + command);
-        switch(command) {
-            case  CONNECT_HFP_OUTGOING:
-                if (mHeadsetService == null) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    return mHeadsetService.connectHeadsetInternal(mDevice);
-                }
-                break;
-            case CONNECT_HFP_INCOMING:
-                if (mHeadsetService == null) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    processIncomingConnectCommand(command);
-                    return true;
-                }
-                break;
-            case CONNECT_A2DP_OUTGOING:
-                if (mA2dpService != null) {
-                    return mA2dpService.connectSinkInternal(mDevice);
-                }
-                break;
-            case CONNECT_A2DP_INCOMING:
-                processIncomingConnectCommand(command);
-                return true;
-            case CONNECT_HID_OUTGOING:
-                return mService.connectInputDeviceInternal(mDevice);
-            case CONNECT_HID_INCOMING:
-                processIncomingConnectCommand(command);
-                return true;
-            case DISCONNECT_HFP_OUTGOING:
-                if (mHeadsetService == null) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    // Disconnect PBAP
-                    // TODO(): Add PBAP to the state machine.
-                    Message m = new Message();
-                    m.what = DISCONNECT_PBAP_OUTGOING;
-                    deferMessage(m);
-                    if (mHeadsetService.getPriority(mDevice) ==
-                        BluetoothHeadset.PRIORITY_AUTO_CONNECT) {
-                        mHeadsetService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
-                    }
-                    return mHeadsetService.disconnectHeadsetInternal(mDevice);
-                }
-                break;
-            case DISCONNECT_HFP_INCOMING:
-                // ignore
-                return true;
-            case DISCONNECT_A2DP_INCOMING:
-                // ignore
-                return true;
-            case DISCONNECT_A2DP_OUTGOING:
-                if (mA2dpService != null) {
-                    if (mA2dpService.getPriority(mDevice) ==
-                        BluetoothA2dp.PRIORITY_AUTO_CONNECT) {
-                        mA2dpService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
-                    }
-                    return mA2dpService.disconnectSinkInternal(mDevice);
-                }
-                break;
-            case DISCONNECT_HID_INCOMING:
-                // ignore
-                return true;
-            case DISCONNECT_HID_OUTGOING:
-                if (mService.getInputDevicePriority(mDevice) ==
-                    BluetoothInputDevice.PRIORITY_AUTO_CONNECT) {
-                    mService.setInputDevicePriority(mDevice, BluetoothInputDevice.PRIORITY_ON);
-                }
-                return mService.disconnectInputDeviceInternal(mDevice);
-            case DISCONNECT_PBAP_OUTGOING:
-                if (!mPbapServiceConnected) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    return mPbapService.disconnect();
-                }
-                break;
-            case UNPAIR:
-                writeTimerValue(INIT_INCOMING_REJECT_TIMER);
-                setTrust(CONNECTION_ACCESS_UNDEFINED);
-                return mService.removeBondInternal(mDevice.getAddress());
-            default:
-                Log.e(TAG, "Error: Unknown Command");
-        }
-        return false;
-    }
-
-    private void processIncomingConnectCommand(int command) {
-        // Check if device is already trusted
-        int access = getTrust();
-        if (access == BluetoothDevice.CONNECTION_ACCESS_YES) {
-            handleIncomingConnection(command, true);
-        } else if (access == BluetoothDevice.CONNECTION_ACCESS_NO &&
-                   !readIncomingAllowedValue()) {
-            handleIncomingConnection(command, false);
-        } else {
-            sendConnectionAccessIntent();
-            Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_EXPIRY);
-            sendMessageDelayed(msg,
-                               CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT);
-        }
-    }
-
-    private void handleConnectionOfOtherProfiles(int command) {
-        // The white paper recommendations mentions that when there is a
-        // link loss, it is the responsibility of the remote device to connect.
-        // Many connect only 1 profile - and they connect the second profile on
-        // some user action (like play being pressed) and so we need this code.
-        // Auto Connect code only connects to the last connected device - which
-        // is useful in cases like when the phone reboots. But consider the
-        // following case:
-        // User is connected to the car's phone and  A2DP profile.
-        // User comes to the desk  and places the phone in the dock
-        // (or any speaker or music system or even another headset) and thus
-        // gets connected to the A2DP profile.  User goes back to the car.
-        // Ideally the car's system is supposed to send incoming connections
-        // from both Handsfree and A2DP profile. But they don't. The Auto
-        // connect code, will not work here because we only auto connect to the
-        // last connected device for that profile which in this case is the dock.
-        // Now suppose a user is using 2 headsets simultaneously, one for the
-        // phone profile one for the A2DP profile. If this is the use case, we
-        // expect the user to use the preference to turn off the A2DP profile in
-        // the Settings screen for the first headset. Else, after link loss,
-        // there can be an incoming connection from the first headset which
-        // might result in the connection of the A2DP profile (if the second
-        // headset is slower) and thus the A2DP profile on the second headset
-        // will never get connected.
-        //
-        // TODO(): Handle other profiles here.
-        switch (command) {
-            case CONNECT_HFP_INCOMING:
-                // Connect A2DP if there is no incoming connection
-                // If the priority is OFF - don't auto connect.
-                if (mA2dpService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON ||
-                        mA2dpService.getPriority(mDevice) ==
-                            BluetoothProfile.PRIORITY_AUTO_CONNECT) {
-                    Message msg = new Message();
-                    msg.what = CONNECT_OTHER_PROFILES;
-                    msg.arg1 = CONNECT_A2DP_OUTGOING;
-                    sendMessageDelayed(msg, CONNECT_OTHER_PROFILES_DELAY);
-                }
-                break;
-            case CONNECT_A2DP_INCOMING:
-                // This is again against spec. HFP incoming connections should be made
-                // before A2DP, so we should not hit this case. But many devices
-                // don't follow this.
-                if (mHeadsetService != null &&
-                    (mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON ||
-                        mHeadsetService.getPriority(mDevice) ==
-                            BluetoothProfile.PRIORITY_AUTO_CONNECT)) {
-                    Message msg = new Message();
-                    msg.what = CONNECT_OTHER_PROFILES;
-                    msg.arg1 = CONNECT_HFP_OUTGOING;
-                    sendMessageDelayed(msg, CONNECT_OTHER_PROFILES_DELAY);
-                }
-                break;
-            default:
-                break;
-        }
-
-    }
-
-    /*package*/ BluetoothDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Quit the state machine, only to be called by BluetoothService.
-     *
-     * @hide
-     */
-    public void doQuit() {
-        this.quit();
-    }
-
-    private void log(String message) {
-        if (DBG) {
-            Log.i(TAG, "Device:" + mDevice + " Message:" + message);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
old mode 100644
new mode 100755
index 2bbf008..75dfe9d
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -45,7 +45,7 @@
  */
 public final class BluetoothHeadset implements BluetoothProfile {
     private static final String TAG = "BluetoothHeadset";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the Headset
@@ -219,7 +219,38 @@
     private Context mContext;
     private ServiceListener mServiceListener;
     private IBluetoothHeadset mService;
-    BluetoothAdapter mAdapter;
+    private BluetoothAdapter mAdapter;
+
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (DBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (DBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth Headset Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
 
     /**
      * Create a BluetoothHeadset proxy object.
@@ -228,6 +259,16 @@
         mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
         if (!context.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
             Log.e(TAG, "Could not bind to Bluetooth Headset Service");
         }
@@ -239,11 +280,27 @@
      * results once close() has been called. Multiple invocations of close()
      * are ok.
      */
-    /*package*/ synchronized void close() {
+    /*package*/ void close() {
         if (DBG) log("close()");
-        if (mConnection != null) {
-            mContext.unbindService(mConnection);
-            mConnection = null;
+
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
         }
         mServiceListener = null;
     }
@@ -398,7 +455,8 @@
         if (mService != null && isEnabled() &&
             isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
+                priority != BluetoothProfile.PRIORITY_ON &&
+                priority != BluetoothProfile.PRIORITY_AUTO_CONNECT) {
               return false;
             }
             try {
@@ -562,25 +620,6 @@
     }
 
     /**
-     * Cancel the outgoing connection.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean cancelConnectThread() {
-        if (DBG) log("cancelConnectThread");
-        if (mService != null && isEnabled()) {
-            try {
-                return mService.cancelConnectThread();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Accept the incoming connection.
      * Note: This is an internal function and shouldn't be exposed
      *
@@ -600,25 +639,6 @@
     }
 
     /**
-     * Create the connect thread for the incoming connection.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean createIncomingConnect(BluetoothDevice device) {
-        if (DBG) log("createIncomingConnect");
-        if (mService != null && isEnabled()) {
-            try {
-                return mService.createIncomingConnect(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Reject the incoming connection.
      * @hide
      */
@@ -636,63 +656,6 @@
     }
 
     /**
-     * Connect to a Bluetooth Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean connectHeadsetInternal(BluetoothDevice device) {
-        if (DBG) log("connectHeadsetInternal");
-        if (mService != null && isEnabled()) {
-            try {
-                return mService.connectHeadsetInternal(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
-     * Disconnect a Bluetooth Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean disconnectHeadsetInternal(BluetoothDevice device) {
-        if (DBG) log("disconnectHeadsetInternal");
-        if (mService != null && !isDisabled()) {
-            try {
-                 return mService.disconnectHeadsetInternal(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
-     * Set the audio state of the Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean setAudioState(BluetoothDevice device, int state) {
-        if (DBG) log("setAudioState");
-        if (mService != null && !isDisabled()) {
-            try {
-                return mService.setAudioState(device, state);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Get the current audio state of the Headset.
      * Note: This is an internal function and shouldn't be exposed
      *
@@ -712,6 +675,75 @@
     }
 
     /**
+     * Check if Bluetooth SCO audio is connected.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @return true if SCO is connected,
+     *         false otherwise or on error
+     * @hide
+     */
+    public boolean isAudioOn() {
+        if (DBG) log("isAudioOn()");
+        if (mService != null && isEnabled()) {
+            try {
+              return mService.isAudioOn();
+            } catch (RemoteException e) {
+              Log.e(TAG,  Log.getStackTraceString(new Throwable()));
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+
+    }
+
+    /**
+     * Initiates a connection of headset audio.
+     * It setup SCO channel with remote connected headset device.
+     *
+     * @return true if successful
+     *         false if there was some error such as
+     *               there is no connected headset
+     * @hide
+     */
+    public boolean connectAudio() {
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.connectAudio();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
+     * Initiates a disconnection of headset audio.
+     * It tears down the SCO channel from remote headset device.
+     *
+     * @return true if successful
+     *         false if there was some error such as
+     *               there is no connected SCO channel
+     * @hide
+     */
+    public boolean disconnectAudio() {
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.disconnectAudio();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
      * Initiates a SCO channel connection with the headset (if connected).
      * Also initiates a virtual voice call for Handsfree devices as many devices
      * do not accept SCO audio without a call.
@@ -760,6 +792,68 @@
         return false;
     }
 
+    /**
+     * Notify Headset of phone state change.
+     * This is a backdoor for phone app to call BluetoothHeadset since
+     * there is currently not a good way to get precise call state change outside
+     * of phone app.
+     *
+     * @hide
+     */
+    public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
+                                  int type) {
+        if (mService != null && isEnabled()) {
+            try {
+                mService.phoneStateChanged(numActive, numHeld, callState, number, type);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
+    /**
+     * Notify Headset of phone roam state change.
+     * This is a backdoor for phone app to call BluetoothHeadset since
+     * there is currently not a good way to get roaming state change outside
+     * of phone app.
+     *
+     * @hide
+     */
+    public void roamChanged(boolean roaming) {
+        if (mService != null && isEnabled()) {
+            try {
+                mService.roamChanged(roaming);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
+    /**
+     * Send Headset of CLCC response
+     *
+     * @hide
+     */
+    public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
+                             String number, int type) {
+        if (mService != null && isEnabled()) {
+            try {
+                mService.clccResponse(index, direction, status, mode, mpty, number, type);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
     private ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index f850c02..4a0bc7e 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -16,7 +16,10 @@
 
 package android.bluetooth;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -54,7 +57,7 @@
  */
 public final class BluetoothHealth implements BluetoothProfile {
     private static final String TAG = "BluetoothHealth";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Health Profile Source Role - the health device.
@@ -94,6 +97,37 @@
     /** @hide */
     public static final int HEALTH_OPERATION_NOT_ALLOWED = 6005;
 
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (DBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (DBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothHealth.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth Health Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
+
 
     /**
      * Register an application configuration that acts as a Health SINK.
@@ -427,35 +461,74 @@
     /** Health App Configuration un-registration failure */
     public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3;
 
+    private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetooth mService;
+    private IBluetoothHealth mService;
     BluetoothAdapter mAdapter;
 
     /**
      * Create a BluetoothHealth proxy object.
      */
-    /*package*/ BluetoothHealth(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+    /*package*/ BluetoothHealth(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetooth.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, this);
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
             }
-        } else {
-            Log.w(TAG, "Bluetooth Service not available!");
+        }
 
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        if (!context.bindService(new Intent(IBluetoothHealth.class.getName()), mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth Health Service");
         }
     }
 
     /*package*/ void close() {
+        if (DBG) log("close()");
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
+        }
         mServiceListener = null;
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothHealth.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, BluetoothHealth.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.HEALTH);
+            }
+        }
+    };
+
     private boolean isEnabled() {
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
 
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
old mode 100644
new mode 100755
index 1a9e011..bff966d
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -18,7 +18,10 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -41,7 +44,7 @@
  */
 public final class BluetoothInputDevice implements BluetoothProfile {
     private static final String TAG = "BluetoothInputDevice";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the Input
@@ -66,6 +69,22 @@
         "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
 
     /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PROTOCOL_MODE_CHANGED =
+        "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
+
+
+    /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
+        "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
+
+
+    /**
      * Return codes for the connect and disconnect Bluez / Dbus calls.
      * @hide
      */
@@ -91,34 +110,159 @@
      */
     public static final int INPUT_OPERATION_SUCCESS = 5004;
 
+    /**
+     * @hide
+     */
+    public static final int PROTOCOL_REPORT_MODE = 0;
+
+    /**
+     * @hide
+     */
+    public static final int PROTOCOL_BOOT_MODE = 1;
+
+    /**
+     * @hide
+     */
+    public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
+
+    /*  int reportType, int reportType, int bufferSize */
+    /**
+     * @hide
+     */
+    public static final byte REPORT_TYPE_INPUT = 0;
+
+    /**
+     * @hide
+     */
+    public static final byte REPORT_TYPE_OUTPUT = 1;
+
+    /**
+     * @hide
+     */
+    public static final byte REPORT_TYPE_FEATURE = 2;
+
+    /**
+     * @hide
+     */
+    public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
+
+    /**
+     * @hide
+     */
+    public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
+
+    private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetooth mService;
+    private IBluetoothInputDevice mService;
+
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (DBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (DBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothInputDevice.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth HID Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
 
     /**
      * Create a BluetoothInputDevice proxy object for interacting with the local
      * Bluetooth Service which handles the InputDevice profile
      *
      */
-    /*package*/ BluetoothInputDevice(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+    /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetooth.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, this);
-            }
-        } else {
-            Log.w(TAG, "Bluetooth Service not available!");
 
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        if (!context.bindService(new Intent(IBluetoothInputDevice.class.getName()),
+                                 mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth HID Service");
         }
     }
 
     /*package*/ void close() {
+        if (DBG) log("close()");
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+           }
+        }
         mServiceListener = null;
     }
 
@@ -144,10 +288,9 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connectInputDevice(device);
+                return mService.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -185,10 +328,9 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnectInputDevice(device);
+                return mService.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -205,7 +347,7 @@
         if (DBG) log("getConnectedDevices()");
         if (mService != null && isEnabled()) {
             try {
-                return mService.getConnectedInputDevices();
+                return mService.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
@@ -222,7 +364,7 @@
         if (DBG) log("getDevicesMatchingStates()");
         if (mService != null && isEnabled()) {
             try {
-                return mService.getInputDevicesMatchingConnectionStates(states);
+                return mService.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
@@ -237,10 +379,9 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getInputDeviceConnectionState(device);
+                return mService.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
@@ -267,14 +408,13 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF &&
                 priority != BluetoothProfile.PRIORITY_ON) {
               return false;
             }
             try {
-                return mService.setInputDevicePriority(device, priority);
+                return mService.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -299,10 +439,9 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (DBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getInputDevicePriority(device);
+                return mService.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.PRIORITY_OFF;
@@ -312,6 +451,24 @@
         return BluetoothProfile.PRIORITY_OFF;
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothInputDevice.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
+            }
+        }
+    };
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
@@ -324,6 +481,158 @@
        return false;
     }
 
+
+    /**
+     * Initiate virtual unplug for a HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean virtualUnplug(BluetoothDevice device) {
+        if (DBG) log("virtualUnplug(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.virtualUnplug(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+
+    }
+
+    /**
+    * Send Get_Protocol_Mode command to the connected HID input device.
+    *
+    * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+    *
+    * @param device Remote Bluetooth Device
+    * @return false on immediate error,
+    *true otherwise
+    * @hide
+    */
+    public boolean getProtocolMode(BluetoothDevice device) {
+        if (DBG) log("getProtocolMode(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getProtocolMode(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+    }
+
+    /**
+     * Send Set_Protocol_Mode command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
+        if (DBG) log("setProtocolMode(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.setProtocolMode(device, protocolMode);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Send Get_Report command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @param reportType Report type
+     * @param reportId Report ID
+     * @param bufferSize Report receiving buffer size
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
+        if (DBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getReport(device, reportType, reportId, bufferSize);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Send Set_Report command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @param reportType Report type
+     * @param report Report receiving buffer size
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean setReport(BluetoothDevice device, byte reportType, String report) {
+        if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.setReport(device, reportType, report);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Send Send_Data command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @param data Data to send
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean sendData(BluetoothDevice device, String report) {
+        if (DBG) log("sendData(" + device + "), report=" + report);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.sendData(device, report);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
     private static void log(String msg) {
       Log.d(TAG, msg);
     }
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 5d9d8be..cae7a73 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -18,7 +18,10 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -27,7 +30,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-
 /**
  * This class provides the APIs to control the Bluetooth Pan
  * Profile.
@@ -41,7 +43,7 @@
  */
 public final class BluetoothPan implements BluetoothProfile {
     private static final String TAG = "BluetoothPan";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the Pan
@@ -76,15 +78,18 @@
      */
     public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
 
+    public static final int PAN_ROLE_NONE = 0;
     /**
      * The local device is acting as a Network Access Point.
      */
     public static final int LOCAL_NAP_ROLE = 1;
+    public static final int REMOTE_NAP_ROLE = 1;
 
     /**
      * The local device is acting as a PAN User.
      */
     public static final int LOCAL_PANU_ROLE = 2;
+    public static final int REMOTE_PANU_ROLE = 2;
 
     /**
      * Return codes for the connect and disconnect Bluez / Dbus calls.
@@ -112,37 +117,77 @@
      */
     public static final int PAN_OPERATION_SUCCESS = 1004;
 
+    private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetooth mService;
+    private IBluetoothPan mPanService;
 
     /**
      * Create a BluetoothPan proxy object for interacting with the local
      * Bluetooth Service which handles the Pan profile
      *
      */
-    /*package*/ BluetoothPan(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+    /*package*/ BluetoothPan(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetooth.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.PAN, this);
-            }
-        } else {
-            Log.w(TAG, "Bluetooth Service not available!");
-
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        try {
+            mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
+        } catch (RemoteException re) {
+            Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re);
         }
+        Log.d(TAG, "BluetoothPan() call bindService");
+        if (!context.bindService(new Intent(IBluetoothPan.class.getName()),
+                                 mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth HID Service");
+        }
+        Log.d(TAG, "BluetoothPan(), bindService called");
     }
 
     /*package*/ void close() {
+        if (DBG) log("close()");
+        if (mConnection != null) {
+            mContext.unbindService(mConnection);
+            mConnection = null;
+        }
         mServiceListener = null;
+        try {
+            mAdapter.getBluetoothManager().unregisterStateChangeCallback(mStateChangeCallback);
+        } catch (RemoteException re) {
+            Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re);
+        }
     }
 
+    protected void finalize() {
+        close();
+    }
+
+    private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() {
+
+        @Override
+        public void onBluetoothStateChange(boolean on) throws RemoteException {
+            //Handle enable request to bind again.
+            if (on) {
+                Log.d(TAG, "onBluetoothStateChange(on) call bindService");
+                if (!mContext.bindService(new Intent(IBluetoothPan.class.getName()),
+                                     mConnection, 0)) {
+                    Log.e(TAG, "Could not bind to Bluetooth HID Service");
+                }
+                Log.d(TAG, "BluetoothPan(), bindService called");
+            } else {
+                if (DBG) Log.d(TAG,"Unbinding service...");
+                synchronized (mConnection) {
+                    try {
+                        mPanService = null;
+                        mContext.unbindService(mConnection);
+                    } catch (Exception re) {
+                        Log.e(TAG,"",re);
+                    }
+                }
+            }
+        }
+    };
+
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
@@ -163,16 +208,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
+        if (mPanService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
-                return mService.connectPanDevice(device);
+                return mPanService.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -204,16 +249,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
+        if (mPanService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
-                return mService.disconnectPanDevice(device);
+                return mPanService.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -222,15 +267,15 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        if (mPanService != null && isEnabled()) {
             try {
-                return mService.getConnectedPanDevices();
+                return mPanService.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -239,15 +284,15 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        if (mPanService != null && isEnabled()) {
             try {
-                return mService.getPanDevicesMatchingConnectionStates(states);
+                return mPanService.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -256,23 +301,23 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
+        if (mPanService != null && isEnabled()
             && isValidDevice(device)) {
             try {
-                return mService.getPanDeviceConnectionState(device);
+                return mPanService.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
     public void setBluetoothTethering(boolean value) {
         if (DBG) log("setBluetoothTethering(" + value + ")");
         try {
-            mService.setBluetoothTethering(value);
+            mPanService.setBluetoothTethering(value);
         } catch (RemoteException e) {
             Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
         }
@@ -281,13 +326,32 @@
     public boolean isTetheringOn() {
         if (DBG) log("isTetheringOn()");
         try {
-            return mService.isTetheringOn();
+            return mPanService.isTetheringOn();
         } catch (RemoteException e) {
             Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-            return false;
         }
+        return false;
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
+            mPanService = IBluetoothPan.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.PAN,
+                                                    BluetoothPan.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected");
+            mPanService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.PAN);
+            }
+        }
+    };
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java
deleted file mode 100644
index b0c0a0b..0000000
--- a/core/java/android/bluetooth/BluetoothProfileState.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.bluetooth;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-/**
- * This state machine is used to serialize the connections
- * to a particular profile. Currently, we only allow one device
- * to be connected to a particular profile.
- * States:
- *      {@link StableState} : No pending commands. Send the
- *      command to the appropriate remote device specific state machine.
- *
- *      {@link PendingCommandState} : A profile connection / disconnection
- *      command is being executed. This will result in a profile state
- *      change. Defer all commands.
- * @hide
- */
-
-public class BluetoothProfileState extends StateMachine {
-    private static final boolean DBG = true;
-    private static final String TAG = "BluetoothProfileState";
-
-    public static final int HFP = 0;
-    public static final int A2DP = 1;
-    public static final int HID = 2;
-
-    static final int TRANSITION_TO_STABLE = 100;
-
-    private int mProfile;
-    private BluetoothDevice mPendingDevice;
-    private PendingCommandState mPendingCommandState = new PendingCommandState();
-    private StableState mStableState = new StableState();
-
-    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (device == null) {
-                return;
-            }
-            if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                if (mProfile == HFP && (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                if (mProfile == A2DP && (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                if (mProfile == HID && (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
-                if (device.equals(mPendingDevice)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            }
-        }
-    };
-
-    public BluetoothProfileState(Context context, int profile) {
-        super("BluetoothProfileState:" + profile);
-        mProfile = profile;
-        addState(mStableState);
-        addState(mPendingCommandState);
-        setInitialState(mStableState);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-        context.registerReceiver(mBroadcastReceiver, filter);
-    }
-
-    private class StableState extends State {
-        @Override
-        public void enter() {
-            log("Entering Stable State");
-            mPendingDevice = null;
-        }
-
-        @Override
-        public boolean processMessage(Message msg) {
-            if (msg.what != TRANSITION_TO_STABLE) {
-                transitionTo(mPendingCommandState);
-            }
-            return true;
-        }
-    }
-
-    private class PendingCommandState extends State {
-        @Override
-        public void enter() {
-            log("Entering PendingCommandState State");
-            dispatchMessage(getCurrentMessage());
-        }
-
-        @Override
-        public boolean processMessage(Message msg) {
-            if (msg.what == TRANSITION_TO_STABLE) {
-                transitionTo(mStableState);
-            } else {
-                dispatchMessage(msg);
-            }
-            return true;
-        }
-
-        private void dispatchMessage(Message msg) {
-            BluetoothDeviceProfileState deviceProfileMgr =
-              (BluetoothDeviceProfileState)msg.obj;
-            int cmd = msg.arg1;
-            if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice())) {
-                mPendingDevice = deviceProfileMgr.getDevice();
-                deviceProfileMgr.sendMessage(cmd);
-            } else {
-                Message deferMsg = new Message();
-                deferMsg.arg1 = cmd;
-                deferMsg.obj = deviceProfileMgr;
-                deferMessage(deferMsg);
-            }
-        }
-    }
-
-    private void log(String message) {
-        if (DBG) {
-            Log.i(TAG, "Message:" + message);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 4021f7b..96be8a2 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -17,6 +17,8 @@
 package android.bluetooth;
 
 import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelUuid;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -86,6 +88,22 @@
     }
 
     /**
+     * Construct a socket for incoming connections.
+     * @param type    type of socket
+     * @param auth    require the remote device to be authenticated
+     * @param encrypt require the connection to be encrypted
+     * @param uuid    uuid
+     * @throws IOException On error, for example Bluetooth not available, or
+     *                     insufficient privileges
+     */
+    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
+            throws IOException {
+        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
+        mChannel = mSocket.getPort();
+    }
+
+
+    /**
      * Block until a connection is established.
      * <p>Returns a connected {@link BluetoothSocket} on successful connection.
      * <p>Once this call returns, it can be called again to accept subsequent
@@ -133,7 +151,9 @@
         mHandler = handler;
         mMessage = message;
     }
-
+    /*package*/ void setServiceName(String ServiceName) {
+        mSocket.setServiceName(ServiceName);
+    }
     /**
      * Returns the channel on which this socket is bound.
      * @hide
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 19d13ef..1bc640f 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -1,32 +1,27 @@
 /*
- * 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.
+ * Copyright (C) 2012 Google Inc.
  */
 
 package android.bluetooth;
 
-import android.bluetooth.IBluetoothCallback;
+import android.os.IBinder;
 import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 
 import java.io.Closeable;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
+import java.util.List;
+import android.net.LocalSocket;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
 /**
  * A connected or connecting Bluetooth socket.
  *
@@ -89,31 +84,40 @@
     /*package*/ static final int EBADFD = 77;
     /*package*/ static final int EADDRINUSE = 98;
 
+    /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
+    /*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
+
     private final int mType;  /* one of TYPE_RFCOMM etc */
-    private final BluetoothDevice mDevice;    /* remote device */
-    private final String mAddress;    /* remote address */
+    private BluetoothDevice mDevice;    /* remote device */
+    private String mAddress;    /* remote address */
     private final boolean mAuth;
     private final boolean mEncrypt;
     private final BluetoothInputStream mInputStream;
     private final BluetoothOutputStream mOutputStream;
-    private final SdpHelper mSdp;
-
+    private final ParcelUuid mUuid;
+    private ParcelFileDescriptor mPfd;
+    private LocalSocket mSocket;
+    private InputStream mSocketIS;
+    private OutputStream mSocketOS;
     private int mPort;  /* RFCOMM channel or L2CAP psm */
+    private int mFd;
+    private String mServiceName;
+    private static int PROXY_CONNECTION_TIMEOUT = 5000;
+
+    private static int SOCK_SIGNAL_SIZE = 16;
 
     private enum SocketState {
         INIT,
         CONNECTED,
-        CLOSED
+        LISTENING,
+        CLOSED,
     }
 
     /** prevents all native calls after destroyNative() */
-    private SocketState mSocketState;
+    private volatile SocketState mSocketState;
 
     /** protects mSocketState */
-    private final ReentrantReadWriteLock mLock;
-
-    /** used by native code only */
-    private int mSocketData;
+    //private final ReentrantReadWriteLock mLock;
 
     /**
      * Construct a BluetoothSocket.
@@ -134,33 +138,52 @@
                 throw new IOException("Invalid RFCOMM channel: " + port);
             }
         }
-        if (uuid == null) {
-            mPort = port;
-            mSdp = null;
-        } else {
-            mSdp = new SdpHelper(device, uuid);
-            mPort = -1;
-        }
+        mUuid = uuid;
         mType = type;
         mAuth = auth;
         mEncrypt = encrypt;
         mDevice = device;
+        mPort = port;
+        mFd = fd;
+
+        mSocketState = SocketState.INIT;
+
         if (device == null) {
-            mAddress = null;
+            // Server socket
+            mAddress = BluetoothAdapter.getDefaultAdapter().getAddress();
         } else {
+            // Remote socket
             mAddress = device.getAddress();
         }
-        if (fd == -1) {
-            initSocketNative();
-        } else {
-            initSocketFromFdNative(fd);
-        }
         mInputStream = new BluetoothInputStream(this);
         mOutputStream = new BluetoothOutputStream(this);
-        mSocketState = SocketState.INIT;
-        mLock = new ReentrantReadWriteLock();
     }
-
+    private BluetoothSocket(BluetoothSocket s) {
+        mUuid = s.mUuid;
+        mType = s.mType;
+        mAuth = s.mAuth;
+        mEncrypt = s.mEncrypt;
+        mPort = s.mPort;
+        mInputStream = new BluetoothInputStream(this);
+        mOutputStream = new BluetoothOutputStream(this);
+        mServiceName = s.mServiceName;
+    }
+    private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException {
+        BluetoothSocket as = new BluetoothSocket(this);
+        as.mSocketState = SocketState.CONNECTED;
+        FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
+        Log.d(TAG, "socket fd passed by stack  fds: " + fds);
+        if(fds == null || fds.length != 1) {
+            Log.e(TAG, "socket fd passed from stack failed, fds: " + fds);
+            throw new IOException("bt socket acept failed");
+        }
+        as.mSocket = new LocalSocket(fds[0]);
+        as.mSocketIS = as.mSocket.getInputStream();
+        as.mSocketOS = as.mSocket.getOutputStream();
+        as.mAddress = RemoteAddr;
+        as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr);
+        return as;
+    }
     /**
      * Construct a BluetoothSocket from address. Used by native code.
      * @param type    type of socket
@@ -186,67 +209,13 @@
             super.finalize();
         }
     }
-
-    /**
-     * Attempt to connect to a remote device.
-     * <p>This method will block until a connection is made or the connection
-     * fails. If this method returns without an exception then this socket
-     * is now connected.
-     * <p>Creating new connections to
-     * remote Bluetooth devices should not be attempted while device discovery
-     * is in progress. Device discovery is a heavyweight procedure on the
-     * Bluetooth adapter and will significantly slow a device connection.
-     * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
-     * discovery. Discovery is not managed by the Activity,
-     * but is run as a system service, so an application should always call
-     * {@link BluetoothAdapter#cancelDiscovery()} even if it
-     * did not directly request a discovery, just to be sure.
-     * <p>{@link #close} can be used to abort this call from another thread.
-     * @throws IOException on error, for example connection failure
-     */
-    public void connect() throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-
-            if (mSdp != null) {
-                mPort = mSdp.doSdp();  // blocks
-            }
-
-            connectNative();  // blocks
-            mSocketState = SocketState.CONNECTED;
-        } finally {
-            mLock.readLock().unlock();
-        }
-    }
-
-    /**
-     * Immediately close this socket, and release all associated resources.
-     * <p>Causes blocked calls on this socket in other threads to immediately
-     * throw an IOException.
-     */
-    public void close() throws IOException {
-        // abort blocking operations on the socket
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) return;
-            if (mSdp != null) {
-                mSdp.cancel();
-            }
-            abortNative();
-        } finally {
-            mLock.readLock().unlock();
-        }
-
-        // all native calls are guaranteed to immediately return after
-        // abortNative(), so this lock should immediately acquire
-        mLock.writeLock().lock();
-        try {
-            mSocketState = SocketState.CLOSED;
-            destroyNative();
-        } finally {
-            mLock.writeLock().unlock();
-        }
+    private int getSecurityFlags() {
+        int flags = 0;
+        if(mAuth)
+            flags |= SEC_FLAG_AUTH;
+        if(mEncrypt)
+            flags |= SEC_FLAG_ENCRYPT;
+        return flags;
     }
 
     /**
@@ -286,7 +255,64 @@
      *         false if not connected
      */
     public boolean isConnected() {
-        return (mSocketState == SocketState.CONNECTED);
+        return mSocketState == SocketState.CONNECTED;
+    }
+
+    /*package*/ void setServiceName(String name) {
+        mServiceName = name;
+    }
+
+    /**
+     * Attempt to connect to a remote device.
+     * <p>This method will block until a connection is made or the connection
+     * fails. If this method returns without an exception then this socket
+     * is now connected.
+     * <p>Creating new connections to
+     * remote Bluetooth devices should not be attempted while device discovery
+     * is in progress. Device discovery is a heavyweight procedure on the
+     * Bluetooth adapter and will significantly slow a device connection.
+     * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
+     * discovery. Discovery is not managed by the Activity,
+     * but is run as a system service, so an application should always call
+     * {@link BluetoothAdapter#cancelDiscovery()} even if it
+     * did not directly request a discovery, just to be sure.
+     * <p>{@link #close} can be used to abort this call from another thread.
+     * @throws IOException on error, for example connection failure
+     */
+    public void connect() throws IOException {
+        if (mDevice == null) throw new IOException("Connect is called on null device");
+
+        try {
+            // TODO(BT) derive flag from auth and encrypt
+            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
+            IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
+            if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
+            mPfd = bluetoothProxy.connectSocket(mDevice, mType,
+                    mUuid, mPort, getSecurityFlags());
+            synchronized(this)
+            {
+                Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
+                if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
+                if (mPfd == null) throw new IOException("bt socket connect failed");
+                FileDescriptor fd = mPfd.getFileDescriptor();
+                mSocket = new LocalSocket(fd);
+                mSocketIS = mSocket.getInputStream();
+                mSocketOS = mSocket.getOutputStream();
+            }
+            int channel = readInt(mSocketIS);
+            if (channel <= 0)
+                throw new IOException("bt socket connect failed");
+            mPort = channel;
+            waitSocketSignal(mSocketIS);
+            synchronized(this)
+            {
+                if (mSocketState == SocketState.CLOSED)
+                    throw new IOException("bt socket closed");
+                mSocketState = SocketState.CONNECTED;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, Log.getStackTraceString(new Throwable()));
+        }
     }
 
     /**
@@ -294,129 +320,170 @@
      * so that BluetoothAdapter can check the error code for EADDRINUSE
      */
     /*package*/ int bindListen() {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) return EBADFD;
-            return bindListenNative();
-        } finally {
-            mLock.readLock().unlock();
+        int ret;
+        if (mSocketState == SocketState.CLOSED) return EBADFD;
+        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
+        if (bluetoothProxy == null) {
+            Log.e(TAG, "bindListen fail, reason: bluetooth is off");
+            return -1;
         }
+        try {
+            mPfd = bluetoothProxy.createSocketChannel(mType, mServiceName,
+                    mUuid, mPort, getSecurityFlags());
+        } catch (RemoteException e) {
+            Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            // TODO(BT) right error code?
+            return -1;
+        }
+
+        // read out port number
+        try {
+            synchronized(this) {
+                Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
+                if(mSocketState != SocketState.INIT) return EBADFD;
+                if(mPfd == null) return -1;
+                FileDescriptor fd = mPfd.getFileDescriptor();
+                Log.d(TAG, "bindListen(), new LocalSocket ");
+                mSocket = new LocalSocket(fd);
+                Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() ");
+                mSocketIS = mSocket.getInputStream();
+                mSocketOS = mSocket.getOutputStream();
+            }
+            Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS);
+            int channel = readInt(mSocketIS);
+            synchronized(this) {
+                if(mSocketState == SocketState.INIT)
+                    mSocketState = SocketState.LISTENING;
+            }
+            Log.d(TAG, "channel: " + channel);
+            if (mPort == -1) {
+                mPort = channel;
+            } // else ASSERT(mPort == channel)
+            ret = 0;
+        } catch (IOException e) {
+            Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
+            return -1;
+        }
+        return ret;
     }
 
     /*package*/ BluetoothSocket accept(int timeout) throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-
-            BluetoothSocket acceptedSocket = acceptNative(timeout);
-            mSocketState = SocketState.CONNECTED;
-            return acceptedSocket;
-        } finally {
-            mLock.readLock().unlock();
+        BluetoothSocket acceptedSocket;
+        if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state");
+        // TODO(BT) wait on an incoming connection
+        String RemoteAddr = waitSocketSignal(mSocketIS);
+        synchronized(this)
+        {
+            if (mSocketState != SocketState.LISTENING)
+                throw new IOException("bt socket is not in listen state");
+            acceptedSocket = acceptSocket(RemoteAddr);
+            //quick drop the reference of the file handle
         }
+        // TODO(BT) rfcomm socket only supports one connection, return this?
+        // return this;
+        return acceptedSocket;
     }
 
     /*package*/ int available() throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            return availableNative();
-        } finally {
-            mLock.readLock().unlock();
-        }
+        Log.d(TAG, "available: " + mSocketIS);
+        return mSocketIS.available();
     }
 
     /*package*/ int read(byte[] b, int offset, int length) throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            return readNative(b, offset, length);
-        } finally {
-            mLock.readLock().unlock();
-        }
+
+            Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
+            int ret = mSocketIS.read(b, offset, length);
+            if(ret < 0)
+                throw new IOException("bt socket closed, read return: " + ret);
+            Log.d(TAG, "read out:  " + mSocketIS + " ret: " + ret);
+            return ret;
     }
 
     /*package*/ int write(byte[] b, int offset, int length) throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            return writeNative(b, offset, length);
-        } finally {
-            mLock.readLock().unlock();
-        }
+
+            Log.d(TAG, "write: " + mSocketOS + " length: " + length);
+            mSocketOS.write(b, offset, length);
+            // There is no good way to confirm since the entire process is asynchronous anyway
+            Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
+            return length;
     }
 
-    private native void initSocketNative() throws IOException;
-    private native void initSocketFromFdNative(int fd) throws IOException;
-    private native void connectNative() throws IOException;
-    private native int bindListenNative();
-    private native BluetoothSocket acceptNative(int timeout) throws IOException;
-    private native int availableNative() throws IOException;
-    private native int readNative(byte[] b, int offset, int length) throws IOException;
-    private native int writeNative(byte[] b, int offset, int length) throws IOException;
-    private native void abortNative() throws IOException;
-    private native void destroyNative() throws IOException;
-    /**
-     * Throws an IOException for given posix errno. Done natively so we can
-     * use strerr to convert to string error.
-     */
-    /*package*/ native void throwErrnoNative(int errno) throws IOException;
-
-    /**
-     * Helper to perform blocking SDP lookup.
-     */
-    private static class SdpHelper extends IBluetoothCallback.Stub {
-        private final IBluetooth service;
-        private final ParcelUuid uuid;
-        private final BluetoothDevice device;
-        private int channel;
-        private boolean canceled;
-        public SdpHelper(BluetoothDevice device, ParcelUuid uuid) {
-            service = BluetoothDevice.getService();
-            this.device = device;
-            this.uuid = uuid;
-            canceled = false;
+    @Override
+    public void close() throws IOException {
+        Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState);
+        if(mSocketState == SocketState.CLOSED)
+            return;
+        else
+        {
+            synchronized(this)
+            {
+                 if(mSocketState == SocketState.CLOSED)
+                    return;
+                 mSocketState = SocketState.CLOSED;
+                 Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS +
+                        ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket);
+                 if(mSocket != null) {
+                    Log.d(TAG, "Closing mSocket: " + mSocket);
+                    mSocket.shutdownInput();
+                    mSocket.shutdownOutput();
+                    mSocket.close();
+                    mSocket = null;
+                }
+                if(mPfd != null)
+                    mPfd.detachFd();
+           }
         }
-        /**
-         * Returns the RFCOMM channel for the UUID, or throws IOException
-         * on failure.
-         */
-        public synchronized int doSdp() throws IOException {
-            if (canceled) throw new IOException("Service discovery canceled");
-            channel = -1;
+        // TODO(BT) unbind proxy,
+    }
 
-            boolean inProgress = false;
-            try {
-                inProgress = service.fetchRemoteUuids(device.getAddress(), uuid, this);
-            } catch (RemoteException e) {Log.e(TAG, "", e);}
+    /*package */ void removeChannel() {
+    }
 
-            if (!inProgress) throw new IOException("Unable to start Service Discovery");
-
-            try {
-                /* 12 second timeout as a precaution - onRfcommChannelFound
-                 * should always occur before the timeout */
-                wait(12000);   // block
-
-            } catch (InterruptedException e) {}
-
-            if (canceled) throw new IOException("Service discovery canceled");
-            if (channel < 1) throw new IOException("Service discovery failed");
-
-            return channel;
+    /*package */ int getPort() {
+        return mPort;
+    }
+    private String convertAddr(final byte[] addr)  {
+        return String.format("%02X:%02X:%02X:%02X:%02X:%02X",
+                addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]);
+    }
+    private String waitSocketSignal(InputStream is) throws IOException {
+        byte [] sig = new byte[SOCK_SIGNAL_SIZE];
+        int ret = readAll(is, sig);
+        Log.d(TAG, "waitSocketSignal read 16 bytes signal ret: " + ret);
+        ByteBuffer bb = ByteBuffer.wrap(sig);
+        bb.order(ByteOrder.nativeOrder());
+        int size = bb.getShort();
+        byte [] addr = new byte[6];
+        bb.get(addr);
+        int channel = bb.getInt();
+        int status = bb.getInt();
+        String RemoteAddr = convertAddr(addr);
+        Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: "
+                + RemoteAddr + ", channel: " + channel + ", status: " + status);
+        if(status != 0)
+            throw new IOException("Connection failure, status: " + status);
+        return RemoteAddr;
+    }
+    private int readAll(InputStream is, byte[] b) throws IOException {
+        int left = b.length;
+        while(left > 0) {
+            int ret = is.read(b, b.length - left, left);
+            if(ret <= 0)
+                 throw new IOException("read failed, socket might closed, read ret: " + ret);
+            left -= ret;
+            if(left != 0)
+                Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) +
+                            ", expect size: " + b.length);
         }
-        /** Object cannot be re-used after calling cancel() */
-        public synchronized void cancel() {
-            if (!canceled) {
-                canceled = true;
-                channel = -1;
-                notifyAll();  // unblock
-            }
-        }
-        public synchronized void onRfcommChannelFound(int channel) {
-            if (!canceled) {
-                this.channel = channel;
-                notifyAll();  // unblock
-            }
-        }
+        return b.length;
+    }
+
+    private int readInt(InputStream is) throws IOException {
+        byte[] ibytes = new byte[4];
+        int ret = readAll(is, ibytes);
+        Log.d(TAG, "inputStream.read ret: " + ret);
+        ByteBuffer bb = ByteBuffer.wrap(ibytes);
+        bb.order(ByteOrder.nativeOrder());
+        return bb.getInt();
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 83d1bda..b2b5d81 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.os.INetworkManagementService;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfoInternal;
@@ -28,6 +31,11 @@
 import android.os.Handler;
 import android.os.Message;
 import android.util.Log;
+import java.net.InterfaceAddress;
+import android.net.LinkAddress;
+import android.net.RouteInfo;
+import java.net.Inet4Address;
+import android.os.SystemProperties;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -54,9 +62,8 @@
     private NetworkInfo mNetworkInfo;
 
     private BluetoothPan mBluetoothPan;
-    private BluetoothDevice mDevice;
     private static String mIface;
-
+    private Thread mDhcpThread;
     /* For sending events to connectivity service handler */
     private Handler mCsHandler;
     private Context mContext;
@@ -92,8 +99,10 @@
      * Begin monitoring connectivity
      */
     public void startMonitoring(Context context, Handler target) {
+        Log.d(TAG, "startMonitoring: target: " + target);
         mContext = context;
         mCsHandler = target;
+        Log.d(TAG, "startMonitoring: mCsHandler: " + mCsHandler);
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
@@ -259,38 +268,91 @@
         return "net.tcp.buffersize.wifi";
     }
 
+    private static short countPrefixLength(byte [] mask) {
+        short count = 0;
+        for (byte b : mask) {
+            for (int i = 0; i < 8; ++i) {
+                if ((b & (1 << i)) != 0) {
+                    ++count;
+                }
+            }
+        }
+        return count;
+    }
 
-    public synchronized void startReverseTether(String iface, BluetoothDevice device) {
+
+    private boolean readLinkProperty(String iface) {
+        String DhcpPrefix = "dhcp." + iface + ".";
+        String ip = SystemProperties.get(DhcpPrefix + "ipaddress");
+        String dns1 = SystemProperties.get(DhcpPrefix + "dns1");
+        String dns2 = SystemProperties.get(DhcpPrefix + "dns2");
+        String gateway = SystemProperties.get(DhcpPrefix + "gateway");
+        String mask = SystemProperties.get(DhcpPrefix + "mask");
+        if(ip.isEmpty() || gateway.isEmpty()) {
+            Log.e(TAG, "readLinkProperty, ip: " +  ip + ", gateway: " + gateway + ", can not be empty");
+            return false;
+        }
+        int PrefixLen = countPrefixLength(NetworkUtils.numericToInetAddress(mask).getAddress());
+        mLinkProperties.addLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(ip), PrefixLen));
+        RouteInfo ri = new RouteInfo(NetworkUtils.numericToInetAddress(gateway));
+        mLinkProperties.addRoute(ri);
+        if(!dns1.isEmpty())
+            mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns1));
+        if(!dns2.isEmpty())
+            mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns2));
+        mLinkProperties.setInterfaceName(iface);
+        return true;
+    }
+    public synchronized void startReverseTether(String iface) {
         mIface = iface;
-        mDevice = device;
-        Thread dhcpThread = new Thread(new Runnable() {
+        Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+         mDhcpThread = new Thread(new Runnable() {
             public void run() {
                 //TODO(): Add callbacks for failure and success case.
                 //Currently this thread runs independently.
-                DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
-                if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
-                    Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
-                    return;
+                Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+                String DhcpResultName = "dhcp." + mIface + ".result";;
+                String result = "";
+                Log.d(TAG, "waiting for change of sys prop dhcp result: " + DhcpResultName);
+                for(int i = 0; i < 30*5; i++) {
+                    try { Thread.sleep(200); } catch (InterruptedException ie) { return;}
+                    result = SystemProperties.get(DhcpResultName);
+                    Log.d(TAG, "read " + DhcpResultName + ": " + result);
+                    if(result.equals("failed")) {
+                        Log.e(TAG, "startReverseTether, failed to start dhcp service");
+                        return;
+                    }
+                    if(result.equals("ok")) {
+                        Log.d(TAG, "startReverseTether, dhcp resut: " + result);
+                        if(readLinkProperty(mIface)) {
+
+                            mNetworkInfo.setIsAvailable(true);
+                            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+                            Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+                            if(mCsHandler != null) {
+                                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+                                msg.sendToTarget();
+
+                                msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+                                msg.sendToTarget();
+                            }
+                        }
+                        return;
+                    }
                 }
-                mLinkProperties = dhcpInfoInternal.makeLinkProperties();
-                mLinkProperties.setInterfaceName(mIface);
-
-                mNetworkInfo.setIsAvailable(true);
-                mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
-
-                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
-                msg.sendToTarget();
-
-                msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
-                msg.sendToTarget();
+                Log.d(TAG, "startReverseTether, dhcp failed, resut: " + result);
             }
         });
-        dhcpThread.start();
+        mDhcpThread.start();
     }
 
-    public synchronized void stopReverseTether(String iface) {
-        NetworkUtils.stopDhcp(iface);
-
+    public synchronized void stopReverseTether() {
+        //NetworkUtils.stopDhcp(iface);
+        if(mDhcpThread != null && mDhcpThread.isAlive()) {
+            mDhcpThread.interrupt();
+            try { mDhcpThread.join(); } catch (InterruptedException ie) { return; }
+        }
         mLinkProperties.clear();
         mNetworkInfo.setIsAvailable(false);
         mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java
deleted file mode 100644
index 9ef2eb5..0000000
--- a/core/java/android/bluetooth/HeadsetBase.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.util.Log;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * The base RFCOMM (service) connection for a headset or handsfree device.
- *
- * In the future this class will be removed.
- *
- * @hide
- */
-public final class HeadsetBase {
-    private static final String TAG = "Bluetooth HeadsetBase";
-    private static final boolean DBG = false;
-
-    public static final int RFCOMM_DISCONNECTED = 1;
-
-    public static final int DIRECTION_INCOMING = 1;
-    public static final int DIRECTION_OUTGOING = 2;
-
-    private static int sAtInputCount = 0;  /* TODO: Consider not using a static variable */
-
-    private final BluetoothAdapter mAdapter;
-    private final BluetoothDevice mRemoteDevice;
-    private final String mAddress;  // for native code
-    private final int mRfcommChannel;
-    private int mNativeData;
-    private Thread mEventThread;
-    private volatile boolean mEventThreadInterrupted;
-    private Handler mEventThreadHandler;
-    private int mTimeoutRemainingMs;
-    private final int mDirection;
-    private final long mConnectTimestamp;
-
-    protected AtParser mAtParser;
-
-    private WakeLock mWakeLock;  // held while processing an AT command
-
-    private native static void classInitNative();
-    static {
-        classInitNative();
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNativeDataNative();
-            releaseWakeLock();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private native void cleanupNativeDataNative();
-
-    public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
-                       BluetoothDevice device, int rfcommChannel) {
-        mDirection = DIRECTION_OUTGOING;
-        mConnectTimestamp = System.currentTimeMillis();
-        mAdapter = adapter;
-        mRemoteDevice = device;
-        mAddress = device.getAddress();
-        mRfcommChannel = rfcommChannel;
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
-        mWakeLock.setReferenceCounted(false);
-        initializeAtParser();
-        // Must be called after this.mAddress is set.
-        initializeNativeDataNative(-1);
-    }
-
-    /* Create from an existing rfcomm connection */
-    public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
-                       BluetoothDevice device,
-                       int socketFd, int rfcommChannel, Handler handler) {
-        mDirection = DIRECTION_INCOMING;
-        mConnectTimestamp = System.currentTimeMillis();
-        mAdapter = adapter;
-        mRemoteDevice = device;
-        mAddress = device.getAddress();
-        mRfcommChannel = rfcommChannel;
-        mEventThreadHandler = handler;
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
-        mWakeLock.setReferenceCounted(false);
-        initializeAtParser();
-        // Must be called after this.mAddress is set.
-        initializeNativeDataNative(socketFd);
-    }
-
-    private native void initializeNativeDataNative(int socketFd);
-
-    /* Process an incoming AT command line
-     */
-    protected void handleInput(String input) {
-        acquireWakeLock();
-        long timestamp;
-
-        synchronized(HeadsetBase.class) {
-            if (sAtInputCount == Integer.MAX_VALUE) {
-                sAtInputCount = 0;
-            } else {
-                sAtInputCount++;
-            }
-        }
-
-        if (DBG) timestamp = System.currentTimeMillis();
-        AtCommandResult result = mAtParser.process(input);
-        if (DBG) Log.d(TAG, "Processing " + input + " took " +
-                       (System.currentTimeMillis() - timestamp) + " ms");
-
-        if (result.getResultCode() == AtCommandResult.ERROR) {
-            Log.i(TAG, "Error processing <" + input + ">");
-        }
-
-        sendURC(result.toString());
-
-        releaseWakeLock();
-    }
-
-    /**
-     * Register AT commands that are common to all Headset / Handsets. This
-     * function is called by the HeadsetBase constructor.
-     */
-    protected void initializeAtParser() {
-        mAtParser = new AtParser();
-
-        //TODO(): Get rid of this as there are no parsers registered. But because of dependencies
-        // it needs to be done as part of refactoring HeadsetBase and BluetoothHandsfree
-    }
-
-    public AtParser getAtParser() {
-        return mAtParser;
-    }
-
-    public void startEventThread() {
-        mEventThread =
-            new Thread("HeadsetBase Event Thread") {
-                public void run() {
-                    int last_read_error;
-                    while (!mEventThreadInterrupted) {
-                        String input = readNative(500);
-                        if (input != null) {
-                            handleInput(input);
-                        } else {
-                            last_read_error = getLastReadStatusNative();
-                            if (last_read_error != 0) {
-                                Log.i(TAG, "headset read error " + last_read_error);
-                                if (mEventThreadHandler != null) {
-                                    mEventThreadHandler.obtainMessage(RFCOMM_DISCONNECTED)
-                                            .sendToTarget();
-                                }
-                                disconnectNative();
-                                break;
-                            }
-                        }
-                    }
-                }
-            };
-        mEventThreadInterrupted = false;
-        mEventThread.start();
-    }
-
-    private native String readNative(int timeout_ms);
-    private native int getLastReadStatusNative();
-
-    private void stopEventThread() {
-        mEventThreadInterrupted = true;
-        mEventThread.interrupt();
-        try {
-            mEventThread.join();
-        } catch (java.lang.InterruptedException e) {
-            // FIXME: handle this,
-        }
-        mEventThread = null;
-    }
-
-    public boolean connect(Handler handler) {
-        if (mEventThread == null) {
-            if (!connectNative()) return false;
-            mEventThreadHandler = handler;
-        }
-        return true;
-    }
-    private native boolean connectNative();
-
-    /*
-     * Returns true when either the asynchronous connect is in progress, or
-     * the connect is complete.  Call waitForAsyncConnect() to find out whether
-     * the connect is actually complete, or disconnect() to cancel.
-     */
-
-    public boolean connectAsync() {
-        int ret = connectAsyncNative();
-        return (ret == 0) ? true : false;
-    }
-    private native int connectAsyncNative();
-
-    public int getRemainingAsyncConnectWaitingTimeMs() {
-        return mTimeoutRemainingMs;
-    }
-
-    /*
-     * Returns 1 when an async connect is complete, 0 on timeout, and -1 on
-     * error.  On error, handler will be called, and you need to re-initiate
-     * the async connect.
-     */
-    public int waitForAsyncConnect(int timeout_ms, Handler handler) {
-        int res = waitForAsyncConnectNative(timeout_ms);
-        if (res > 0) {
-            mEventThreadHandler = handler;
-        }
-        return res;
-    }
-    private native int waitForAsyncConnectNative(int timeout_ms);
-
-    public void disconnect() {
-        if (mEventThread != null) {
-            stopEventThread();
-        }
-        disconnectNative();
-    }
-    private native void disconnectNative();
-
-
-    /*
-     * Note that if a remote side disconnects, this method will still return
-     * true until disconnect() is called.  You know when a remote side
-     * disconnects because you will receive the intent
-     * IBluetoothService.REMOTE_DEVICE_DISCONNECTED_ACTION.  If, when you get
-     * this intent, method isConnected() returns true, you know that the
-     * disconnect was initiated by the remote device.
-     */
-
-    public boolean isConnected() {
-        return mEventThread != null;
-    }
-
-    public BluetoothDevice getRemoteDevice() {
-        return mRemoteDevice;
-    }
-
-    public int getDirection() {
-        return mDirection;
-    }
-
-    public long getConnectTimestamp() {
-        return mConnectTimestamp;
-    }
-
-    public synchronized boolean sendURC(String urc) {
-        if (urc.length() > 0) {
-            boolean ret = sendURCNative(urc);
-            return ret;
-        }
-        return true;
-    }
-    private native boolean sendURCNative(String urc);
-
-    private synchronized void acquireWakeLock() {
-        if (!mWakeLock.isHeld()) {
-            mWakeLock.acquire();
-        }
-    }
-
-    private synchronized void releaseWakeLock() {
-        if (mWakeLock.isHeld()) {
-            mWakeLock.release();
-        }
-    }
-
-    public static int getAtInputCount() {
-        return sAtInputCount;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 6075363..d016c26 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -18,9 +18,7 @@
 
 import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.IBluetoothStateChangeCallback;
-import android.bluetooth.IBluetoothHealthCallback;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealthAppConfiguration;
 import android.os.ParcelUuid;
 import android.os.ParcelFileDescriptor;
 
@@ -32,15 +30,15 @@
 interface IBluetooth
 {
     boolean isEnabled();
-    int getBluetoothState();
+    int getState();
     boolean enable();
     boolean enableNoAutoConnect();
-    boolean disable(boolean persistSetting);
+    boolean disable();
 
     String getAddress();
-    String getName();
-    boolean setName(in String name);
     ParcelUuid[] getUuids();
+    boolean setName(in String name);
+    String getName();
 
     int getScanMode();
     boolean setScanMode(int mode, int duration);
@@ -51,77 +49,34 @@
     boolean startDiscovery();
     boolean cancelDiscovery();
     boolean isDiscovering();
-    byte[] readOutOfBandData();
 
     int getAdapterConnectionState();
     int getProfileConnectionState(int profile);
-    boolean changeApplicationBluetoothState(boolean on,
-                                in IBluetoothStateChangeCallback callback, in
-                                IBinder b);
 
-    boolean createBond(in String address);
-    boolean createBondOutOfBand(in String address, in byte[] hash, in byte[] randomizer);
-    boolean cancelBondProcess(in String address);
-    boolean removeBond(in String address);
-    String[] listBonds();
-    int getBondState(in String address);
-    boolean setDeviceOutOfBandData(in String address, in byte[] hash, in byte[] randomizer);
+    BluetoothDevice[] getBondedDevices();
+    boolean createBond(in BluetoothDevice device);
+    boolean cancelBondProcess(in BluetoothDevice device);
+    boolean removeBond(in BluetoothDevice device);
+    int getBondState(in BluetoothDevice device);
 
-    String getRemoteName(in String address);
-    String getRemoteAlias(in String address);
-    boolean setRemoteAlias(in String address, in String name);
-    int getRemoteClass(in String address);
-    ParcelUuid[] getRemoteUuids(in String address);
-    boolean fetchRemoteUuids(in String address, in ParcelUuid uuid, in IBluetoothCallback callback);
-    int getRemoteServiceChannel(in String address, in ParcelUuid uuid);
+    String getRemoteName(in BluetoothDevice device);
+    String getRemoteAlias(in BluetoothDevice device);
+    boolean setRemoteAlias(in BluetoothDevice device, in String name);
+    int getRemoteClass(in BluetoothDevice device);
+    ParcelUuid[] getRemoteUuids(in BluetoothDevice device);
+    boolean fetchRemoteUuids(in BluetoothDevice device);
 
-    boolean setPin(in String address, in byte[] pin);
-    boolean setPasskey(in String address, int passkey);
-    boolean setPairingConfirmation(in String address, boolean confirm);
-    boolean setRemoteOutOfBandData(in String addres);
-    boolean cancelPairingUserInput(in String address);
-
-    boolean setTrust(in String address, in boolean value);
-    boolean getTrustState(in String address);
-    boolean isBluetoothDock(in String address);
-
-    int addRfcommServiceRecord(in String serviceName, in ParcelUuid uuid, int channel, IBinder b);
-    void removeServiceRecord(int handle);
-    boolean allowIncomingProfileConnect(in BluetoothDevice device, boolean value);
-
-    boolean connectHeadset(String address);
-    boolean disconnectHeadset(String address);
-    boolean notifyIncomingConnection(String address, boolean rejected);
-
-    // HID profile APIs
-    boolean connectInputDevice(in BluetoothDevice device);
-    boolean disconnectInputDevice(in BluetoothDevice device);
-    List<BluetoothDevice> getConnectedInputDevices();
-    List<BluetoothDevice> getInputDevicesMatchingConnectionStates(in int[] states);
-    int getInputDeviceConnectionState(in BluetoothDevice device);
-    boolean setInputDevicePriority(in BluetoothDevice device, int priority);
-    int getInputDevicePriority(in BluetoothDevice device);
-
-    boolean isTetheringOn();
-    void setBluetoothTethering(boolean value);
-    int getPanDeviceConnectionState(in BluetoothDevice device);
-    List<BluetoothDevice> getConnectedPanDevices();
-    List<BluetoothDevice> getPanDevicesMatchingConnectionStates(in int[] states);
-    boolean connectPanDevice(in BluetoothDevice device);
-    boolean disconnectPanDevice(in BluetoothDevice device);
-
-    // HDP profile APIs
-    boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
-        in IBluetoothHealthCallback callback);
-    boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
-    boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
-    boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
-        int channelType);
-    boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
-    ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
-    List<BluetoothDevice> getConnectedHealthDevices();
-    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
-    int getHealthDeviceConnectionState(in BluetoothDevice device);
+    boolean setPin(in BluetoothDevice device, boolean accept, int len, in byte[] pinCode);
+    boolean setPasskey(in BluetoothDevice device, boolean accept, int len, in byte[]
+    passkey);
+    boolean setPairingConfirmation(in BluetoothDevice device, boolean accept);
 
     void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState);
+
+    void registerCallback(in IBluetoothCallback callback);
+    void unregisterCallback(in IBluetoothCallback callback);
+
+    // For Socket
+    ParcelFileDescriptor connectSocket(in BluetoothDevice device, int type, in ParcelUuid uuid, int port, int flag);
+    ParcelFileDescriptor createSocketChannel(int type, in String serviceName, in ParcelUuid uuid, int port, int flag);
 }
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 444dd1e..1f10998 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -33,12 +33,4 @@
     boolean setPriority(in BluetoothDevice device, int priority);
     int getPriority(in BluetoothDevice device);
     boolean isA2dpPlaying(in BluetoothDevice device);
-
-    // Internal APIs
-    boolean suspendSink(in BluetoothDevice device);
-    boolean resumeSink(in BluetoothDevice device);
-    boolean connectSinkInternal(in BluetoothDevice device);
-    boolean disconnectSinkInternal(in BluetoothDevice device);
-    boolean allowIncomingConnect(in BluetoothDevice device, boolean value);
-
 }
diff --git a/core/java/android/bluetooth/IBluetoothCallback.aidl b/core/java/android/bluetooth/IBluetoothCallback.aidl
index 8edb3f4..e280978 100644
--- a/core/java/android/bluetooth/IBluetoothCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothCallback.aidl
@@ -23,5 +23,6 @@
  */
 interface IBluetoothCallback
 {
-    void onRfcommChannelFound(int channel);
+    //void onRfcommChannelFound(int channel);
+    void onBluetoothStateChange(int prevState, int newState);
 }
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index ec00527..fc7627a 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -40,15 +40,17 @@
     int getBatteryUsageHint(in BluetoothDevice device);
 
     // Internal functions, not be made public
-    boolean createIncomingConnect(in BluetoothDevice device);
     boolean acceptIncomingConnect(in BluetoothDevice device);
     boolean rejectIncomingConnect(in BluetoothDevice device);
-    boolean cancelConnectThread();
-    boolean connectHeadsetInternal(in BluetoothDevice device);
-    boolean disconnectHeadsetInternal(in BluetoothDevice device);
-    boolean setAudioState(in BluetoothDevice device, int state);
     int getAudioState(in BluetoothDevice device);
 
+    boolean isAudioOn();
+    boolean connectAudio();
+    boolean disconnectAudio();
     boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device);
     boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device);
+    void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
+    void roamChanged(boolean roam);
+    void clccResponse(int index, int direction, int status, int mode, boolean mpty,
+                      String number, int type);
 }
diff --git a/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl b/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl
new file mode 100644
index 0000000..163e4e2
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+package android.bluetooth;
+
+/**
+ * API for Bluetooth Headset Phone Service in phone app
+ *
+ * {@hide}
+ */
+interface IBluetoothHeadsetPhone {
+  // Internal functions, not be made public
+  boolean answerCall();
+  boolean hangupCall();
+  boolean sendDtmf(int dtmf);
+  boolean processChld(int chld);
+  String getNetworkOperator();
+  String getSubscriberNumber();
+  boolean listCurrentCalls();
+  boolean queryPhoneState();
+
+  // Internal for phone app to call
+  void updateBtHandsfreeAfterRadioTechnologyChange();
+  void cdmaSwapSecondCallState();
+  void cdmaSetSecondCallState(boolean state);
+}
diff --git a/core/java/android/bluetooth/IBluetoothHealth.aidl b/core/java/android/bluetooth/IBluetoothHealth.aidl
new file mode 100644
index 0000000..e741da4
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHealth.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.bluetooth.IBluetoothHealthCallback;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * API for Bluetooth Health service
+ *
+ * {@hide}
+ */
+interface IBluetoothHealth
+{
+    boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
+        in IBluetoothHealthCallback callback);
+    boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
+    boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+    boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
+        int channelType);
+    boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
+    ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+    List<BluetoothDevice> getConnectedHealthDevices();
+    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
+    int getHealthDeviceConnectionState(in BluetoothDevice device);
+}
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
new file mode 100755
index 0000000..23e6d50
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth HID service
+ *
+ * {@hide}
+ */
+interface IBluetoothInputDevice {
+    // Public API
+    boolean connect(in BluetoothDevice device);
+    boolean disconnect(in BluetoothDevice device);
+    List<BluetoothDevice> getConnectedDevices();
+    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+    int getConnectionState(in BluetoothDevice device);
+    boolean setPriority(in BluetoothDevice device, int priority);
+    int getPriority(in BluetoothDevice device);
+    /**
+    * @hide
+    */
+    boolean getProtocolMode(in BluetoothDevice device);
+    /**
+    * @hide
+    */
+    boolean virtualUnplug(in BluetoothDevice device);
+    /**
+    * @hide
+    */
+    boolean setProtocolMode(in BluetoothDevice device, int protocolMode);
+    /**
+    * @hide
+    */
+    boolean getReport(in BluetoothDevice device, byte reportType, byte reportId, int bufferSize);
+    /**
+    * @hide
+    */
+    boolean setReport(in BluetoothDevice device, byte reportType, String report);
+    /**
+    * @hide
+    */
+    boolean sendData(in BluetoothDevice device, String report);
+}
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
new file mode 100644
index 0000000..f82da82
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothManagerCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
+
+/**
+ * System private API for talking with the Bluetooth service.
+ *
+ * {@hide}
+ */
+interface IBluetoothManager
+{
+    IBluetooth registerAdapter(in IBluetoothManagerCallback callback);
+    void unregisterAdapter(in IBluetoothManagerCallback callback);
+    void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
+    void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
+    boolean isEnabled();
+    boolean enable();
+    boolean disable(boolean persist);
+
+    String getAddress();
+    String getName();
+}
diff --git a/core/java/android/bluetooth/IBluetoothManagerCallback.aidl b/core/java/android/bluetooth/IBluetoothManagerCallback.aidl
new file mode 100644
index 0000000..3e795ea
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothManagerCallback.aidl
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetooth;
+
+/**
+ * API for Communication between BluetoothAdapter and BluetoothManager
+ *
+ * {@hide}
+ */
+interface IBluetoothManagerCallback {
+    void onBluetoothServiceUp(in IBluetooth bluetoothService);
+    void onBluetoothServiceDown();
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/IBluetoothPan.aidl b/core/java/android/bluetooth/IBluetoothPan.aidl
new file mode 100644
index 0000000..b91bd7d
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothPan.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Pan service
+ *
+ * {@hide}
+ */
+interface IBluetoothPan {
+    // Public API
+    boolean isTetheringOn();
+    void setBluetoothTethering(boolean value);
+    boolean connect(in BluetoothDevice device);
+    boolean disconnect(in BluetoothDevice device);
+    List<BluetoothDevice> getConnectedDevices();
+    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+    int getConnectionState(in BluetoothDevice device);
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ffff9be..490165d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1379,6 +1379,7 @@
      *      description (action, category, etc) to match an
      *      {@link IntentFilter} published by a service.
      * @param conn Receives information as the service is started and stopped.
+     *      This must be a valid ServiceConnection object; it must not be null.
      * @param flags Operation options for the binding.  May be 0,
      *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
      *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
@@ -1414,7 +1415,7 @@
      * stop at any time.
      *
      * @param conn The connection interface previously supplied to
-     *             bindService().
+     *             bindService().  This parameter must not be null.
      *
      * @see #bindService
      */
@@ -1906,6 +1907,15 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.bluetooth.BluetoothAdapter} for using Bluetooth.
+     *
+     * @see #getSystemService
+     * @hide
+     */
+    public static final String BLUETOOTH_SERVICE = "bluetooth";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.net.sip.SipManager} for accessing the SIP related service.
      *
      * @see #getSystemService
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3fdf451..d325186 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -571,7 +571,9 @@
  *     <li> {@link #EXTRA_INITIAL_INTENTS}
  *     <li> {@link #EXTRA_INTENT}
  *     <li> {@link #EXTRA_KEY_EVENT}
+ *     <li> {@link #EXTRA_ORIGINATING_URL}
  *     <li> {@link #EXTRA_PHONE_NUMBER}
+ *     <li> {@link #EXTRA_REFERRER}
  *     <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
  *     <li> {@link #EXTRA_REPLACING}
  *     <li> {@link #EXTRA_SHORTCUT_ICON}
@@ -1286,6 +1288,22 @@
             = "android.intent.extra.NOT_UNKNOWN_SOURCE";
 
     /**
+     * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the URL from which the local APK in the Intent
+     * data field originated from.
+     */
+    public static final String EXTRA_ORIGINATING_URL
+            = "android.intent.extra.ORIGINATING_URL";
+
+    /**
+     * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the HTTP referrer associated with the Intent
+     * data field or {@link #EXTRA_ORIGINATING_URL}.
+     */
+    public static final String EXTRA_REFERRER
+            = "android.intent.extra.REFERRER";
+
+    /**
      * Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
      * package.  Tells the installer UI to skip the confirmation with the user
      * if the .apk is replacing an existing one.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e1434b3..cbabc7c 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -298,7 +298,6 @@
      * activity's manifest.
      *
      * Default value is false (no support for RTL).
-     * @hide
      */
     public static final int FLAG_SUPPORTS_RTL = 1<<22;
 
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 90b4247..0d87df5 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -41,6 +41,7 @@
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
 import android.content.IntentSender;
 
 /**
@@ -359,7 +360,8 @@
 
     UserInfo createUser(in String name, int flags);
     boolean removeUser(int userId);
-    void updateUserName(int userId, String name);
+    void setUserName(int userId, String name);
+    ParcelFileDescriptor setUserIcon(int userId);
 
     void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer,
             int flags, in String installerPackageName, in Uri verificationURI,
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7e96ae6..cd7ef0e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2646,7 +2646,7 @@
      * @param name the new name for the user
      * @hide
      */
-    public abstract void updateUserName(int id, String name);
+    public abstract void setUserName(int id, String name);
 
     /**
      * Changes the user's properties specified by the flags.
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index ba5331c..68a7257 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -43,12 +43,18 @@
 
     public int id;
     public String name;
+    public String iconPath;
     public int flags;
 
     public UserInfo(int id, String name, int flags) {
+        this(id, name, null, flags);
+    }
+
+    public UserInfo(int id, String name, String iconPath, int flags) {
         this.id = id;
         this.name = name;
         this.flags = flags;
+        this.iconPath = iconPath;
     }
 
     public boolean isPrimary() {
@@ -68,6 +74,7 @@
 
     public UserInfo(UserInfo orig) {
         name = orig.name;
+        iconPath = orig.iconPath;
         id = orig.id;
         flags = orig.flags;
     }
@@ -84,6 +91,7 @@
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeInt(id);
         dest.writeString(name);
+        dest.writeString(iconPath);
         dest.writeInt(flags);
     }
 
@@ -100,6 +108,7 @@
     private UserInfo(Parcel source) {
         id = source.readInt();
         name = source.readString();
+        iconPath = source.readString();
         flags = source.readInt();
     }
 }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 2df492e..281b843 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -469,13 +469,20 @@
      * {@link android.view.ViewGroup}'s layout_width and layout_height
      * attributes.  This is only here for performance reasons; applications
      * should use {@link #getDimensionPixelSize}.
-     * 
+     *
      * @param index Index of the attribute to retrieve.
      * @param name Textual name of attribute for error reporting.
      * 
      * @return Attribute dimension value multiplied by the appropriate 
      * metric and truncated to integer pixels.
+     *
+     * @throws RuntimeException
+     *             if this TypedArray does not contain an entry for <code>index</code>
+     *
+     * @deprecated Use {@link #getLayoutDimension(int, int)} instead.
+     *
      */
+    @Deprecated
     public int getLayoutDimension(int index, String name) {
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index a6af5c2..1fc1226 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -50,9 +50,6 @@
     private static final String TAG = "DatabaseUtils";
 
     private static final boolean DEBUG = false;
-    private static final boolean LOCAL_LOGV = false;
-
-    private static final String[] countProjection = new String[]{"count(*)"};
 
     /** One of the values returned by {@link #getSqlStatementType(String)}. */
     public static final int STATEMENT_SELECT = 1;
@@ -963,10 +960,15 @@
     }
 
     /**
-     * This class allows users to do multiple inserts into a table but
-     * compile the SQL insert statement only once, which may increase
-     * performance.
+     * This class allows users to do multiple inserts into a table using
+     * the same statement.
+     * <p>
+     * This class is not thread-safe.
+     * </p>
+     *
+     * @deprecated Use {@link SQLiteStatement} instead.
      */
+    @Deprecated
     public static class InsertHelper {
         private final SQLiteDatabase mDb;
         private final String mTableName;
@@ -983,6 +985,13 @@
          * table_info(...)" command that we depend on.
          */
         public static final int TABLE_INFO_PRAGMA_COLUMNNAME_INDEX = 1;
+
+        /**
+         * This field was accidentally exposed in earlier versions of the platform
+         * so we can hide it but we can't remove it.
+         *
+         * @hide
+         */
         public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4;
 
         /**
@@ -1036,7 +1045,7 @@
             sb.append(sbv);
 
             mInsertSQL = sb.toString();
-            if (LOCAL_LOGV) Log.v(TAG, "insert statement is " + mInsertSQL);
+            if (DEBUG) Log.v(TAG, "insert statement is " + mInsertSQL);
         }
 
         private SQLiteStatement getStatement(boolean allowReplace) throws SQLException {
@@ -1069,24 +1078,35 @@
          * @return the row ID of the newly inserted row, or -1 if an
          * error occurred
          */
-        private synchronized long insertInternal(ContentValues values, boolean allowReplace) {
+        private long insertInternal(ContentValues values, boolean allowReplace) {
+            // Start a transaction even though we don't really need one.
+            // This is to help maintain compatibility with applications that
+            // access InsertHelper from multiple threads even though they never should have.
+            // The original code used to lock the InsertHelper itself which was prone
+            // to deadlocks.  Starting a transaction achieves the same mutual exclusion
+            // effect as grabbing a lock but without the potential for deadlocks.
+            mDb.beginTransactionNonExclusive();
             try {
                 SQLiteStatement stmt = getStatement(allowReplace);
                 stmt.clearBindings();
-                if (LOCAL_LOGV) Log.v(TAG, "--- inserting in table " + mTableName);
+                if (DEBUG) Log.v(TAG, "--- inserting in table " + mTableName);
                 for (Map.Entry<String, Object> e: values.valueSet()) {
                     final String key = e.getKey();
                     int i = getColumnIndex(key);
                     DatabaseUtils.bindObjectToProgram(stmt, i, e.getValue());
-                    if (LOCAL_LOGV) {
+                    if (DEBUG) {
                         Log.v(TAG, "binding " + e.getValue() + " to column " +
                               i + " (" + key + ")");
                     }
                 }
-                return stmt.executeInsert();
+                long result = stmt.executeInsert();
+                mDb.setTransactionSuccessful();
+                return result;
             } catch (SQLException e) {
                 Log.e(TAG, "Error inserting " + values + " into table  " + mTableName, e);
                 return -1;
+            } finally {
+                mDb.endTransaction();
             }
         }
 
@@ -1223,7 +1243,7 @@
                         + "execute");
             }
             try {
-                if (LOCAL_LOGV) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
+                if (DEBUG) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
                 return mPreparedStatement.executeInsert();
             } catch (SQLException e) {
                 Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e);
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 46153e7..c2cb1ff 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1674,9 +1674,6 @@
     /**
      * Show the input method. This is a call back to the
      * IMF to handle showing the input method.
-     * Close this input method's soft input area, removing it from the display.
-     * The input method will continue running, but the user can no longer use
-     * it to generate input by touching the screen.
      * @param flags Provides additional operating flags.  Currently may be
      * 0 or have the {@link InputMethodManager#SHOW_FORCED
      * InputMethodManager.} bit set.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5f8793c..fa1ff85 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -137,6 +137,28 @@
     public static final String EXTRA_INET_CONDITION = "inetCondition";
 
     /**
+     * Broadcast action to indicate the change of data activity status
+     * (idle or active) on a network in a recent period.
+     * The network becomes active when data transimission is started, or
+     * idle if there is no data transimition for a period of time.
+     * {@hide}
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DATA_ACTIVITY_CHANGE = "android.net.conn.DATA_ACTIVITY_CHANGE";
+    /**
+     * The lookup key for an enum that indicates the network device type on which this data activity
+     * change happens.
+     * {@hide}
+     */
+    public static final String EXTRA_DEVICE_TYPE = "deviceType";
+    /**
+     * The lookup key for a boolean that indicates the device is active or not. {@code true} means
+     * it is actively sending or receiving data and {@code false} means it is idle.
+     * {@hide}
+     */
+    public static final String EXTRA_IS_ACTIVE = "isActive";
+
+    /**
      * Broadcast Action: The setting for background data usage has changed
      * values. Use {@link #getBackgroundDataSetting()} to get the current value.
      * <p>
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 28bd289..c690430 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -99,6 +99,10 @@
         public void limitReached(String limitName, String iface) {
             // Ignored.
         }
+
+        public void interfaceClassDataActivityChanged(String label, boolean active) {
+            // Ignored.
+        }
     }
 
     private EthernetDataTracker() {
@@ -230,6 +234,10 @@
                             mNetworkInfo.setExtraInfo(mHwAddr);
                         }
                     }
+
+                    // if a DHCP client had previously been started for this interface, then stop it
+                    NetworkUtils.stopDhcp(mIface);
+
                     reconnect();
                     break;
                 }
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index a97f203..6f4dd5f 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -62,4 +62,11 @@
      */
     void limitReached(String limitName, String iface);
 
+    /**
+     * Interface data activity status is changed.
+     *
+     * @param iface The interface.
+     * @param active  True if the interface is actively transmitting data, false if it is idle.
+     */
+    void interfaceClassDataActivityChanged(String label, boolean active);
 }
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 3ee8a80..34e0d9a 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -42,6 +42,15 @@
         isBound = false;
         isConnected = false;
     }
+    /**
+     * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
+     * @hide
+     */
+    public LocalSocket(FileDescriptor fd) throws IOException {
+        this(new LocalSocketImpl(fd));
+        isBound = true;
+        isConnected = true;
+    }
 
     /**
      * for use with AndroidServerSocket
diff --git a/core/java/android/net/ParseException.java b/core/java/android/net/ParseException.java
index 000fa68..68b209b 100644
--- a/core/java/android/net/ParseException.java
+++ b/core/java/android/net/ParseException.java
@@ -17,10 +17,9 @@
 package android.net;
 
 /**
- * 
- *
- * When WebAddress Parser Fails, this exception is thrown
+ * Thrown when parsing a URL fails.
  */
+// See non-public class {@link WebAddress}.
 public class ParseException extends RuntimeException {
     public String response;
 
diff --git a/core/java/android/net/arp/ArpPeer.java b/core/java/android/net/arp/ArpPeer.java
index 8e666bc..5f68fdf 100644
--- a/core/java/android/net/arp/ArpPeer.java
+++ b/core/java/android/net/arp/ArpPeer.java
@@ -16,8 +16,12 @@
 
 package android.net.arp;
 
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
 import android.os.SystemClock;
 import android.util.Log;
+
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Inet6Address;
@@ -35,6 +39,8 @@
  * @hide
  */
 public class ArpPeer {
+    private static final boolean DBG = false;
+    private static final String TAG = "ArpPeer";
     private String mInterfaceName;
     private final InetAddress mMyAddr;
     private final byte[] mMyMac = new byte[6];
@@ -46,7 +52,6 @@
     private static final int ARP_LENGTH = 28;
     private static final int MAC_ADDR_LENGTH = 6;
     private static final int IPV4_LENGTH = 4;
-    private static final String TAG = "ArpPeer";
 
     public ArpPeer(String interfaceName, InetAddress myAddr, String mac,
                    InetAddress peer) throws SocketException {
@@ -123,6 +128,41 @@
         return null;
     }
 
+    public static boolean doArp(String myMacAddress, LinkProperties linkProperties,
+            int timeoutMillis, int numArpPings, int minArpResponses) {
+        String interfaceName = linkProperties.getInterfaceName();
+        InetAddress inetAddress = null;
+        InetAddress gateway = null;
+        boolean success;
+
+        for (LinkAddress la : linkProperties.getLinkAddresses()) {
+            inetAddress = la.getAddress();
+            break;
+        }
+
+        for (RouteInfo route : linkProperties.getRoutes()) {
+            gateway = route.getGateway();
+            break;
+        }
+
+        try {
+            ArpPeer peer = new ArpPeer(interfaceName, inetAddress, myMacAddress, gateway);
+            int responses = 0;
+            for (int i=0; i < numArpPings; i++) {
+                if(peer.doArp(timeoutMillis) != null) responses++;
+            }
+            if (DBG) Log.d(TAG, "ARP test result: " + responses + "/" + numArpPings);
+            success = (responses >= minArpResponses);
+            peer.close();
+        } catch (SocketException se) {
+            //Consider an Arp socket creation issue as a successful Arp
+            //test to avoid any wifi connectivity issues
+            Log.e(TAG, "ARP test initiation failure: " + se);
+            success = true;
+        }
+        return success;
+    }
+
     public void close() {
         try {
             mSocket.close();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 438c536..2aa6fb5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -71,9 +71,9 @@
     public static final int FULL_WIFI_LOCK = 5;
     
     /**
-     * A constant indicating a scan wifi lock timer
+     * A constant indicating a wifi scan
      */
-    public static final int SCAN_WIFI_LOCK = 6;
+    public static final int WIFI_SCAN = 6;
 
      /**
       * A constant indicating a wifi multicast timer
@@ -136,7 +136,7 @@
     private static final String BATTERY_DATA = "bt";
     private static final String BATTERY_DISCHARGE_DATA = "dc";
     private static final String BATTERY_LEVEL_DATA = "lv";
-    private static final String WIFI_LOCK_DATA = "wfl";
+    private static final String WIFI_DATA = "wfl";
     private static final String MISC_DATA = "m";
     private static final String SCREEN_BRIGHTNESS_DATA = "br";
     private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
@@ -260,8 +260,8 @@
         public abstract void noteWifiStoppedLocked();
         public abstract void noteFullWifiLockAcquiredLocked();
         public abstract void noteFullWifiLockReleasedLocked();
-        public abstract void noteScanWifiLockAcquiredLocked();
-        public abstract void noteScanWifiLockReleasedLocked();
+        public abstract void noteWifiScanStartedLocked();
+        public abstract void noteWifiScanStoppedLocked();
         public abstract void noteWifiMulticastEnabledLocked();
         public abstract void noteWifiMulticastDisabledLocked();
         public abstract void noteAudioTurnedOnLocked();
@@ -270,7 +270,7 @@
         public abstract void noteVideoTurnedOffLocked();
         public abstract long getWifiRunningTime(long batteryRealtime, int which);
         public abstract long getFullWifiLockTime(long batteryRealtime, int which);
-        public abstract long getScanWifiLockTime(long batteryRealtime, int which);
+        public abstract long getWifiScanTime(long batteryRealtime, int which);
         public abstract long getWifiMulticastTime(long batteryRealtime,
                                                   int which);
         public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
@@ -453,7 +453,7 @@
         public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
         public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
         public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
-        public static final int STATE_WIFI_SCAN_LOCK_FLAG = 1<<24;
+        public static final int STATE_WIFI_SCAN_FLAG = 1<<24;
         public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
         // These are on the lower bits used for the command; if they change
         // we need to write another int of data.
@@ -859,7 +859,7 @@
         new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
         new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
         new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
-        new BitDescription(HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG, "wifi_scan_lock"),
+        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan"),
         new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
         new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
         new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
@@ -1326,15 +1326,15 @@
             long rx = u.getTcpBytesReceived(which);
             long tx = u.getTcpBytesSent(which);
             long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
-            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
             long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
             
             if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
             
-            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
                     || uidWifiRunningTime != 0) {
-                dumpLine(pw, uid, category, WIFI_LOCK_DATA, 
-                        fullWifiLockOnTime, scanWifiLockOnTime, uidWifiRunningTime);
+                dumpLine(pw, uid, category, WIFI_DATA,
+                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
             }
 
             if (u.hasUserActivity()) {
@@ -1692,7 +1692,7 @@
             long tcpReceived = u.getTcpBytesReceived(which);
             long tcpSent = u.getTcpBytesSent(which);
             long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
-            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
             long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
             
             if (tcpReceived != 0 || tcpSent != 0) {
@@ -1723,7 +1723,7 @@
                 }
             }
             
-            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
                     || uidWifiRunningTime != 0) {
                 sb.setLength(0);
                 sb.append(prefix); sb.append("    Wifi Running: ");
@@ -1731,12 +1731,12 @@
                         sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
                                 whichBatteryRealtime)); sb.append(")\n");
                 sb.append(prefix); sb.append("    Full Wifi Lock: "); 
-                        formatTimeMs(sb, fullWifiLockOnTime / 1000); 
-                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, 
+                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
                                 whichBatteryRealtime)); sb.append(")\n");
-                sb.append(prefix); sb.append("    Scan Wifi Lock: "); 
-                        formatTimeMs(sb, scanWifiLockOnTime / 1000);
-                        sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime, 
+                sb.append(prefix); sb.append("    Wifi Scan: ");
+                        formatTimeMs(sb, wifiScanTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
                                 whichBatteryRealtime)); sb.append(")");
                 pw.println(sb.toString());
             }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index e7ea355..53bb88a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -152,6 +152,16 @@
     boolean isTetheringStarted();
 
     /**
+     * Start bluetooth reverse tethering services
+     */
+    void startReverseTethering(in String iface);
+
+    /**
+     * Stop currently running bluetooth reserse tethering services
+     */
+    void stopReverseTethering();
+
+    /**
      * Tethers the specified interface
      */
     void tetherInterface(String iface);
@@ -218,17 +228,17 @@
     /**
      * Start Wifi Access Point
      */
-    void startAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
+    void startAccessPoint(in WifiConfiguration wifiConfig, String iface);
 
     /**
      * Stop Wifi Access Point
      */
-    void stopAccessPoint(String wlanIface);
+    void stopAccessPoint(String iface);
 
     /**
      * Set Access Point config
      */
-    void setAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
+    void setAccessPoint(in WifiConfiguration wifiConfig, String iface);
 
     /**
      ** DATA USAGE RELATED
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 903c8b3..b6e606c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -19,19 +19,21 @@
 import android.util.Log;
 
 /**
- * This class gives you control of the power state of the device.  
- * 
- * <p><b>Device battery life will be significantly affected by the use of this API.</b>  Do not
- * acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure
- * to release it as soon as you can.
- * 
- * <p>You can obtain an instance of this class by calling 
+ * This class gives you control of the power state of the device.
+ *
+ * <p>
+ * <b>Device battery life will be significantly affected by the use of this API.</b>
+ * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
+ * possible, and be sure to release them as soon as possible.
+ * </p><p>
+ * You can obtain an instance of this class by calling
  * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- * 
- * <p>The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.  This will
- * create a {@link PowerManager.WakeLock} object.  You can then use methods on this object to 
- * control the power state of the device.  In practice it's quite simple:
- * 
+ * </p><p>
+ * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
+ * This will create a {@link PowerManager.WakeLock} object.  You can then use methods
+ * on the wake lock object to control the power state of the device.
+ * </p><p>
+ * In practice it's quite simple:
  * {@samplecode
  * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
  * PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
@@ -39,11 +41,11 @@
  *   ..screen will stay on during this section..
  * wl.release();
  * }
- * 
- * <p>The following flags are defined, with varying effects on system power.  <i>These flags are
- * mutually exclusive - you may only specify one of them.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ * </p><p>
+ * The following flags are defined, with varying effects on system power.
+ * <i>These flags are mutually exclusive - you may only specify one of them.</i>
  *
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
  *     <thead>
  *     <tr><th>Flag Value</th> 
  *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
@@ -67,15 +69,16 @@
  *     </tr>
  *     </tbody>
  * </table>
- * 
- * <p>*<i>If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers 
- * and even after the user presses the power button.  In all other wakelocks, the CPU will run, but
- * the user can still put the device to sleep using the power button.</i>
- * 
- * <p>In addition, you can add two more flags, which affect behavior of the screen only.  <i>These
- * flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ * </p><p>
+ * *<i>If you hold a partial wake lock, the CPU will continue to run, regardless of any
+ * display timeouts or the state of the screen and even after the user presses the power button.
+ * In all other wake locks, the CPU will run, but the user can still put the device to sleep
+ * using the power button.</i>
+ * </p><p>
+ * In addition, you can add two more flags, which affect behavior of the screen only.
+ * <i>These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
  *
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
  *     <thead>
  *     <tr><th>Flag Value</th> <th>Description</th></tr>
  *     </thead>
@@ -96,73 +99,77 @@
  *     </tr>
  *     </tbody>
  * </table>
- * 
+ * </p><p>
  * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
  * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+ * </p>
  */
-public class PowerManager
-{
+public final class PowerManager {
     private static final String TAG = "PowerManager";
-    
-    /**
+
+    /*
      * These internal values define the underlying power elements that we might
      * want to control individually.  Eventually we'd like to expose them.
      */
-    private static final int WAKE_BIT_CPU_STRONG = 1;
-    private static final int WAKE_BIT_CPU_WEAK = 2;
-    private static final int WAKE_BIT_SCREEN_DIM = 4;
-    private static final int WAKE_BIT_SCREEN_BRIGHT = 8;
-    private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16;
-    private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
-    
+    private static final int WAKE_BIT_CPU_STRONG = 1 << 0;
+    private static final int WAKE_BIT_CPU_WEAK = 1 << 1;
+    private static final int WAKE_BIT_SCREEN_DIM = 1 << 2;
+    private static final int WAKE_BIT_SCREEN_BRIGHT = 1 << 3;
+    private static final int WAKE_BIT_KEYBOARD_BRIGHT = 1 << 4;
+    private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 1 << 5;
+
     private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG
-                                        | WAKE_BIT_CPU_WEAK
-                                        | WAKE_BIT_SCREEN_DIM
-                                        | WAKE_BIT_SCREEN_BRIGHT
-                                        | WAKE_BIT_KEYBOARD_BRIGHT
-                                        | WAKE_BIT_PROXIMITY_SCREEN_OFF;
+            | WAKE_BIT_CPU_WEAK
+            | WAKE_BIT_SCREEN_DIM
+            | WAKE_BIT_SCREEN_BRIGHT
+            | WAKE_BIT_KEYBOARD_BRIGHT
+            | WAKE_BIT_PROXIMITY_SCREEN_OFF;
 
     /**
-     * Wake lock that ensures that the CPU is running.  The screen might
-     * not be on.
+     * Wake lock level: Ensures that the CPU is running; the screen and keyboard
+     * backlight will be allowed to go off.
      */
     public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
 
     /**
-     * Wake lock that ensures that the screen and keyboard are on at
+     * Wake lock level: Ensures that the screen and keyboard backlight are on at
      * full brightness.
      *
-     * <p class="note">Most applications should strongly consider using
-     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
-     * This window flag will be correctly managed by the platform
-     * as the user moves between applications and doesn't require a special permission.</p>
+     * <p class="note">
+     * Most applications should strongly consider using
+     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
+     * of managing their own wake locks.  This window flag will be correctly managed
+     * by the platform as the user moves between applications and doesn't require
+     * a special permission.
+     * </p>
      */
     public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT 
-                                            | WAKE_BIT_KEYBOARD_BRIGHT;
+            | WAKE_BIT_KEYBOARD_BRIGHT;
 
     /**
+     * Wake lock level: Ensures that the screen is on at full brightness;
+     * the keyboard backlight will be allowed to go off.
+     *
      * @deprecated Most applications should use
      * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
      * of this type of wake lock, as it will be correctly managed by the platform
      * as the user moves between applications and doesn't require a special permission.
-     *
-     * Wake lock that ensures that the screen is on at full brightness;
-     * the keyboard backlight will be allowed to go off.
      */
     @Deprecated
     public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT;
 
     /**
-     * Wake lock that ensures that the screen is on (but may be dimmed);
+     * Wake lock level: Ensures that the screen is on (but may be dimmed);
      * the keyboard backlight will be allowed to go off.
      */
     public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM;
 
     /**
-     * Wake lock that turns the screen off when the proximity sensor activates.
-     * Since not all devices have proximity sensors, use
-     * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if
-     * this wake lock mode is supported.
+     * Wake lock level: Turns the screen off when the proximity sensor activates.
+     * <p>
+     * Since not all devices have proximity sensors, use {@link #getSupportedWakeLockFlags()}
+     * to determine whether this wake lock level is supported.
+     * </p>
      *
      * {@hide}
      */
@@ -170,7 +177,7 @@
 
     /**
      * Flag for {@link WakeLock#release release(int)} to defer releasing a
-     * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns
+     * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wake lock until the proximity sensor returns
      * a negative value.
      *
      * {@hide}
@@ -178,25 +185,29 @@
     public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
 
     /**
+     * Wake lock flag: Turn the screen on when the wake lock is acquired.
+     * <p>
      * Normally wake locks don't actually wake the device, they just cause
-     * it to remain on once it's already on.  Think of the video player
-     * app as the normal behavior.  Notifications that pop up and want
+     * the screen to remain on once it's already on.  Think of the video player
+     * application as the normal behavior.  Notifications that pop up and want
      * the device to be on are the exception; use this flag to be like them.
-     * <p> 
-     * Does not work with PARTIAL_WAKE_LOCKs.
+     * </p><p>
+     * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
      */
-    public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
+    public static final int ACQUIRE_CAUSES_WAKEUP = 1 << 28;
 
     /**
-     * When this wake lock is released, poke the user activity timer
+     * Wake lock flag: When this wake lock is released, poke the user activity timer
      * so the screen stays on for a little longer.
      * <p>
-     * Will not turn the screen on if it is not already on.  See {@link #ACQUIRE_CAUSES_WAKEUP}
-     * if you want that.
-     * <p>
-     * Does not work with PARTIAL_WAKE_LOCKs.
+     * Will not turn the screen on if it is not already on.
+     * See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
+     * </p><p>
+     * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
      */
-    public static final int ON_AFTER_RELEASE = 0x20000000;
+    public static final int ON_AFTER_RELEASE = 1 << 29;
 
     /**
      * Brightness value to use when battery is low.
@@ -222,179 +233,253 @@
      */
     public static final int BRIGHTNESS_OFF = 0;
 
+    final IPowerManager mService;
+    final Handler mHandler;
+
     /**
-     * Class lets you say that you need to have the device on.
+     * {@hide}
+     */
+    public PowerManager(IPowerManager service, Handler handler) {
+        mService = service;
+        mHandler = handler;
+    }
+
+    /**
+     * Creates a new wake lock with the specified level and flags.
      * <p>
-     * Call release when you are done and don't need the lock anymore.
+     * The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
+     * combined using the logical OR operator.
+     * </p><p>
+     * The wake lock levels are: {@link #PARTIAL_WAKE_LOCK},
+     * {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK}
+     * and {@link #SCREEN_BRIGHT_WAKE_LOCK}.  Exactly one wake lock level must be
+     * specified as part of the {@code levelAndFlags} parameter.
+     * </p><p>
+     * The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP}
+     * and {@link #ON_AFTER_RELEASE}.  Multiple flags can be combined as part of the
+     * {@code levelAndFlags} parameters.
+     * </p><p>
+     * Call {@link WakeLock#acquire() acquire()} on the object to acquire the
+     * wake lock, and {@link WakeLock#release release()} when you are done.
+     * </p><p>
+     * {@samplecode
+     * PowerManager pm = (PowerManager)mContext.getSystemService(
+     *                                          Context.POWER_SERVICE);
+     * PowerManager.WakeLock wl = pm.newWakeLock(
+     *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
+     *                                      | PowerManager.ON_AFTER_RELEASE,
+     *                                      TAG);
+     * wl.acquire();
+     * // ... do work...
+     * wl.release();
+     * }
+     * </p><p>
+     * Although a wake lock can be created without special permissions,
+     * the {@link android.Manifest.permission#WAKE_LOCK} permission is
+     * required to actually acquire or release the wake lock that is returned.
+     * </p><p class="note">
+     * If using this to keep the screen on, you should strongly consider using
+     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
+     * This window flag will be correctly managed by the platform
+     * as the user moves between applications and doesn't require a special permission.
+     * </p>
+     *
+     * @param levelAndFlags Combination of wake lock level and flag values defining
+     * the requested behavior of the WakeLock.
+     * @param tag Your class name (or other tag) for debugging purposes.
+     *
+     * @see WakeLock#acquire()
+     * @see WakeLock#release()
+     * @see #PARTIAL_WAKE_LOCK
+     * @see #FULL_WAKE_LOCK
+     * @see #SCREEN_DIM_WAKE_LOCK
+     * @see #SCREEN_BRIGHT_WAKE_LOCK
+     * @see #ACQUIRE_CAUSES_WAKEUP
+     * @see #ON_AFTER_RELEASE
+     */
+    public WakeLock newWakeLock(int levelAndFlags, String tag) {
+        switch (levelAndFlags & LOCK_MASK) {
+        case PARTIAL_WAKE_LOCK:
+        case SCREEN_DIM_WAKE_LOCK:
+        case SCREEN_BRIGHT_WAKE_LOCK:
+        case FULL_WAKE_LOCK:
+        case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+            break;
+        default:
+            throw new IllegalArgumentException("Must specify a wake lock level.");
+        }
+        if (tag == null) {
+            throw new IllegalArgumentException("The tag must not be null.");
+        }
+        return new WakeLock(levelAndFlags, tag);
+    }
+
+    /**
+     * Notifies the power manager that user activity happened.
+     * <p>
+     * Turns the device from whatever state it's in to full on, and resets
+     * the auto-off timer.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
+     * time base.  This timestamp is used to correctly order the user activity with
+     * other power management functions.  It should be set
+     * to the timestamp of the input event that caused the user activity.
+     * @param noChangeLights If true, does not cause the keyboard backlight to turn on
+     * because of this event.  This is set when the power key is pressed.
+     * We want the device to stay on while the button is down, but we're about
+     * to turn off the screen so we don't want the keyboard backlight to turn on again.
+     * Otherwise the lights flash on and then off and it looks weird.
+     */
+    public void userActivity(long when, boolean noChangeLights) {
+        try {
+            mService.userActivity(when, noChangeLights);
+        } catch (RemoteException e) {
+        }
+    }
+
+   /**
+     * Forces the device to go to sleep.
+     * <p>
+     * Overrides all the wake locks that are held.  This is what happen when the power
+     * key is pressed to turn off the screen.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param time The time when the request to go to sleep was issued, in the
+     * {@link SystemClock#uptimeMillis()} time base.  This timestamp is used to correctly
+     * order the user activity with other power management functions.  It should be set
+     * to the timestamp of the input event that caused the request to go to sleep.
+     */
+    public void goToSleep(long time) {
+        try {
+            mService.goToSleep(time);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Sets the brightness of the backlights (screen, keyboard, button).
+     * <p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param brightness The brightness value from 0 to 255.
+     *
+     * {@hide}
+     */
+    public void setBacklightBrightness(int brightness) {
+        try {
+            mService.setBacklightBrightness(brightness);
+        } catch (RemoteException e) {
+        }
+    }
+
+   /**
+     * Returns the set of wake lock levels and flags for {@link #newWakeLock}
+     * that are supported on the device.
+     * <p>
+     * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
+     * is supported:
+     * {@samplecode
+     * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+     * int supportedFlags = pm.getSupportedWakeLockFlags();
+     * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
+     *         == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
+     * }
+     * </p>
+     *
+     * @return The set of supported WakeLock flags.
+     *
+     * {@hide}
+     */
+    public int getSupportedWakeLockFlags() {
+        try {
+            return mService.getSupportedWakeLockFlags();
+        } catch (RemoteException e) {
+            return 0;
+        }
+    }
+
+    /**
+      * Returns whether the screen is currently on.
+      * <p>
+      * Only indicates whether the screen is on.  The screen could be either bright or dim.
+      * </p><p>
+      * {@samplecode
+      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+      * boolean isScreenOn = pm.isScreenOn();
+      * }
+      * </p>
+      *
+      * @return whether the screen is on (bright or dim).
+      */
+    public boolean isScreenOn() {
+        try {
+            return mService.isScreenOn();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Reboot the device.  Will not return if the reboot is successful.
+     * <p>
+     * Requires the {@link android.Manifest.permission#REBOOT} permission.
+     * </p>
+     *
+     * @param reason code to pass to the kernel (e.g., "recovery") to
+     *               request special boot modes, or null.
+     */
+    public void reboot(String reason) {
+        try {
+            mService.reboot(reason);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * A wake lock is a mechanism to indicate that your application needs
+     * to have the device stay on.
      * <p>
      * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
      * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+     * Obtain a wake lock by calling {@link PowerManager#newWakeLock(int, String)}.
+     * </p><p>
+     * Call {@link #acquire()} to acquire the wake lock and force the device to stay
+     * on at the level that was requested when the wake lock was created.
+     * </p><p>
+     * Call {@link #release()} when you are done and don't need the lock anymore.
+     * It is very important to do this as soon as possible to avoid running down the
+     * device's battery excessively.
+     * </p>
      */
-    public class WakeLock
-    {
-        static final int RELEASE_WAKE_LOCK = 1;
+    public final class WakeLock {
+        private final int mFlags;
+        private final String mTag;
+        private final IBinder mToken;
+        private int mCount;
+        private boolean mRefCounted = true;
+        private boolean mHeld;
+        private WorkSource mWorkSource;
 
-        Runnable mReleaser = new Runnable() {
+        private final Runnable mReleaser = new Runnable() {
             public void run() {
                 release();
             }
         };
-	
-        int mFlags;
-        String mTag;
-        IBinder mToken;
-        int mCount = 0;
-        boolean mRefCounted = true;
-        boolean mHeld = false;
-        WorkSource mWorkSource;
 
-        WakeLock(int flags, String tag)
-        {
-            switch (flags & LOCK_MASK) {
-            case PARTIAL_WAKE_LOCK:
-            case SCREEN_DIM_WAKE_LOCK:
-            case SCREEN_BRIGHT_WAKE_LOCK:
-            case FULL_WAKE_LOCK:
-            case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
-                break;
-            default:
-                throw new IllegalArgumentException();
-            }
-
+        WakeLock(int flags, String tag) {
             mFlags = flags;
             mTag = tag;
             mToken = new Binder();
         }
 
-        /**
-         * Sets whether this WakeLock is ref counted.
-         *
-         * <p>Wake locks are reference counted by default.
-         *
-         * @param value true for ref counted, false for not ref counted.
-         */
-        public void setReferenceCounted(boolean value)
-        {
-            mRefCounted = value;
-        }
-
-        /**
-         * Makes sure the device is on at the level you asked when you created
-         * the wake lock.
-         */
-        public void acquire()
-        {
-            synchronized (mToken) {
-                acquireLocked();
-            }
-        }
-
-        /**
-         * Makes sure the device is on at the level you asked when you created
-         * the wake lock. The lock will be released after the given timeout.
-         * 
-         * @param timeout Release the lock after the give timeout in milliseconds.
-         */
-        public void acquire(long timeout) {
-            synchronized (mToken) {
-                acquireLocked();
-                mHandler.postDelayed(mReleaser, timeout);
-            }
-        }
-        
-        private void acquireLocked() {
-            if (!mRefCounted || mCount++ == 0) {
-                mHandler.removeCallbacks(mReleaser);
-                try {
-                    mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
-                } catch (RemoteException e) {
-                }
-                mHeld = true;
-            }
-        }
-
-        /**
-         * Release your claim to the CPU or screen being on.
-         *
-         * <p>
-         * It may turn off shortly after you release it, or it may not if there
-         * are other wake locks held.
-         */
-        public void release() {
-            release(0);
-        }
-
-        /**
-         * Release your claim to the CPU or screen being on.
-         * @param flags Combination of flag values to modify the release behavior.
-         *              Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
-         *
-         * <p>
-         * It may turn off shortly after you release it, or it may not if there
-         * are other wake locks held.
-         *
-         * {@hide}
-         */
-        public void release(int flags) {
-            synchronized (mToken) {
-                if (!mRefCounted || --mCount == 0) {
-                    mHandler.removeCallbacks(mReleaser);
-                    try {
-                        mService.releaseWakeLock(mToken, flags);
-                    } catch (RemoteException e) {
-                    }
-                    mHeld = false;
-                }
-                if (mCount < 0) {
-                    throw new RuntimeException("WakeLock under-locked " + mTag);
-                }
-            }
-        }
-
-        public boolean isHeld()
-        {
-            synchronized (mToken) {
-                return mHeld;
-            }
-        }
-
-        public void setWorkSource(WorkSource ws) {
-            synchronized (mToken) {
-                if (ws != null && ws.size() == 0) {
-                    ws = null;
-                }
-                boolean changed = true;
-                if (ws == null) {
-                    mWorkSource = null;
-                } else if (mWorkSource == null) {
-                    changed = mWorkSource != null;
-                    mWorkSource = new WorkSource(ws);
-                } else {
-                    changed = mWorkSource.diff(ws);
-                    if (changed) {
-                        mWorkSource.set(ws);
-                    }
-                }
-                if (changed && mHeld) {
-                    try {
-                        mService.updateWakeLockWorkSource(mToken, mWorkSource);
-                    } catch (RemoteException e) {
-                    }
-                }
-            }
-        }
-
-        public String toString() {
-            synchronized (mToken) {
-                return "WakeLock{"
-                    + Integer.toHexString(System.identityHashCode(this))
-                    + " held=" + mHeld + ", refCount=" + mCount + "}";
-            }
-        }
-
         @Override
-        protected void finalize() throws Throwable
-        {
+        protected void finalize() throws Throwable {
             synchronized (mToken) {
                 if (mHeld) {
                     Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
@@ -405,180 +490,174 @@
                 }
             }
         }
-    }
 
-    /**
-     * Get a wake lock at the level of the flags parameter.  Call
-     * {@link WakeLock#acquire() acquire()} on the object to acquire the
-     * wake lock, and {@link WakeLock#release release()} when you are done.
-     *
-     * {@samplecode
-     *PowerManager pm = (PowerManager)mContext.getSystemService(
-     *                                          Context.POWER_SERVICE);
-     *PowerManager.WakeLock wl = pm.newWakeLock(
-     *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
-     *                                      | PowerManager.ON_AFTER_RELEASE,
-     *                                      TAG);
-     *wl.acquire();
-     * // ...
-     *wl.release();
-     * }
-     *
-     * <p class="note">If using this to keep the screen on, you should strongly consider using
-     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
-     * This window flag will be correctly managed by the platform
-     * as the user moves between applications and doesn't require a special permission.</p>
-     *
-     * @param flags Combination of flag values defining the requested behavior of the WakeLock.
-     * @param tag Your class name (or other tag) for debugging purposes.
-     *
-     * @see WakeLock#acquire()
-     * @see WakeLock#release()
-     */
-    public WakeLock newWakeLock(int flags, String tag)
-    {
-        if (tag == null) {
-            throw new NullPointerException("tag is null in PowerManager.newWakeLock");
+        /**
+         * Sets whether this WakeLock is reference counted.
+         * <p>
+         * Wake locks are reference counted by default.  If a wake lock is
+         * reference counted, then each call to {@link #acquire()} must be
+         * balanced by an equal number of calls to {@link #release()}.  If a wake
+         * lock is not reference counted, then one call to {@link #release()} is
+         * sufficient to undo the effect of all previous calls to {@link #acquire()}.
+         * </p>
+         *
+         * @param value True to make the wake lock reference counted, false to
+         * make the wake lock non-reference counted.
+         */
+        public void setReferenceCounted(boolean value) {
+            synchronized (mToken) {
+                mRefCounted = value;
+            }
         }
-        return new WakeLock(flags, tag);
-    }
 
-    /**
-     * User activity happened.
-     * <p>
-     * Turns the device from whatever state it's in to full on, and resets
-     * the auto-off timer.
-     *
-     * @param when is used to order this correctly with the wake lock calls.
-     *          This time should be in the {@link SystemClock#uptimeMillis
-     *          SystemClock.uptimeMillis()} time base.
-     * @param noChangeLights should be true if you don't want the lights to
-     *          turn on because of this event.  This is set when the power
-     *          key goes down.  We want the device to stay on while the button
-     *          is down, but we're about to turn off.  Otherwise the lights
-     *          flash on and then off and it looks weird.
-     */
-    public void userActivity(long when, boolean noChangeLights)
-    {
-        try {
-            mService.userActivity(when, noChangeLights);
-        } catch (RemoteException e) {
+        /**
+         * Acquires the wake lock.
+         * <p>
+         * Ensures that the device is on at the level requested when
+         * the wake lock was created.
+         * </p>
+         */
+        public void acquire() {
+            synchronized (mToken) {
+                acquireLocked();
+            }
+        }
+
+        /**
+         * Acquires the wake lock with a timeout.
+         * <p>
+         * Ensures that the device is on at the level requested when
+         * the wake lock was created.  The lock will be released after the given timeout
+         * expires.
+         * </p>
+         *
+         * @param timeout The timeout after which to release the wake lock, in milliseconds.
+         */
+        public void acquire(long timeout) {
+            synchronized (mToken) {
+                acquireLocked();
+                mHandler.postDelayed(mReleaser, timeout);
+            }
+        }
+
+        private void acquireLocked() {
+            if (!mRefCounted || mCount++ == 0) {
+                // Do this even if the wake lock is already thought to be held (mHeld == true)
+                // because non-reference counted wake locks are not always properly released.
+                // For example, the keyguard's wake lock might be forcibly released by the
+                // power manager without the keyguard knowing.  A subsequent call to acquire
+                // should immediately acquire the wake lock once again despite never having
+                // been explicitly released by the keyguard.
+                mHandler.removeCallbacks(mReleaser);
+                try {
+                    mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
+                } catch (RemoteException e) {
+                }
+                mHeld = true;
+            }
+        }
+
+        /**
+         * Releases the wake lock.
+         * <p>
+         * This method releases your claim to the CPU or screen being on.
+         * The screen may turn off shortly after you release the wake lock, or it may
+         * not if there are other wake locks still held.
+         * </p>
+         */
+        public void release() {
+            release(0);
+        }
+
+        /**
+         * Releases the wake lock with flags to modify the release behavior.
+         * <p>
+         * This method releases your claim to the CPU or screen being on.
+         * The screen may turn off shortly after you release the wake lock, or it may
+         * not if there are other wake locks still held.
+         * </p>
+         *
+         * @param flags Combination of flag values to modify the release behavior.
+         * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
+         *
+         * {@hide}
+         */
+        public void release(int flags) {
+            synchronized (mToken) {
+                if (!mRefCounted || --mCount == 0) {
+                    mHandler.removeCallbacks(mReleaser);
+                    if (mHeld) {
+                        try {
+                            mService.releaseWakeLock(mToken, flags);
+                        } catch (RemoteException e) {
+                        }
+                        mHeld = false;
+                    }
+                }
+                if (mCount < 0) {
+                    throw new RuntimeException("WakeLock under-locked " + mTag);
+                }
+            }
+        }
+
+        /**
+         * Returns true if the wake lock has been acquired but not yet released.
+         *
+         * @return True if the wake lock is held.
+         */
+        public boolean isHeld() {
+            synchronized (mToken) {
+                return mHeld;
+            }
+        }
+
+        /**
+         * Sets the work source associated with the wake lock.
+         * <p>
+         * The work source is used to determine on behalf of which application
+         * the wake lock is being held.  This is useful in the case where a
+         * service is performing work on behalf of an application so that the
+         * cost of that work can be accounted to the application.
+         * </p>
+         *
+         * @param ws The work source, or null if none.
+         */
+        public void setWorkSource(WorkSource ws) {
+            synchronized (mToken) {
+                if (ws != null && ws.size() == 0) {
+                    ws = null;
+                }
+
+                final boolean changed;
+                if (ws == null) {
+                    changed = mWorkSource != null;
+                    mWorkSource = null;
+                } else if (mWorkSource == null) {
+                    changed = true;
+                    mWorkSource = new WorkSource(ws);
+                } else {
+                    changed = mWorkSource.diff(ws);
+                    if (changed) {
+                        mWorkSource.set(ws);
+                    }
+                }
+
+                if (changed && mHeld) {
+                    try {
+                        mService.updateWakeLockWorkSource(mToken, mWorkSource);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            synchronized (mToken) {
+                return "WakeLock{"
+                    + Integer.toHexString(System.identityHashCode(this))
+                    + " held=" + mHeld + ", refCount=" + mCount + "}";
+            }
         }
     }
-
-   /**
-     * Force the device to go to sleep. Overrides all the wake locks that are
-     * held.
-     * 
-     * @param time is used to order this correctly with the wake lock calls. 
-     *          The time  should be in the {@link SystemClock#uptimeMillis 
-     *          SystemClock.uptimeMillis()} time base.
-     */
-    public void goToSleep(long time) 
-    {
-        try {
-            mService.goToSleep(time);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * sets the brightness of the backlights (screen, keyboard, button).
-     *
-     * @param brightness value from 0 to 255
-     *
-     * {@hide}
-     */
-    public void setBacklightBrightness(int brightness)
-    {
-        try {
-            mService.setBacklightBrightness(brightness);
-        } catch (RemoteException e) {
-        }
-    }
-
-   /**
-     * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
-     * that are supported on the device.
-     * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
-     * is supported:
-     *
-     * {@samplecode
-     * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-     * int supportedFlags = pm.getSupportedWakeLockFlags();
-     *  boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
-     *                                  == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
-     * }
-     *
-     * @return the set of supported WakeLock flags.
-     *
-     * {@hide}
-     */
-    public int getSupportedWakeLockFlags()
-    {
-        try {
-            return mService.getSupportedWakeLockFlags();
-        } catch (RemoteException e) {
-            return 0;
-        }
-    }
-
-    /**
-      * Returns whether the screen is currently on. The screen could be bright
-      * or dim.
-      *
-      * {@samplecode
-      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-      * boolean isScreenOn = pm.isScreenOn();
-      * }
-      *
-      * @return whether the screen is on (bright or dim).
-      */
-    public boolean isScreenOn()
-    {
-        try {
-            return mService.isScreenOn();
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Reboot the device.  Will not return if the reboot is
-     * successful.  Requires the {@link android.Manifest.permission#REBOOT}
-     * permission.
-     *
-     * @param reason code to pass to the kernel (e.g., "recovery") to
-     *               request special boot modes, or null.
-     */
-    public void reboot(String reason)
-    {
-        try {
-            mService.reboot(reason);
-        } catch (RemoteException e) {
-        }
-    }
-
-    private PowerManager()
-    {
-    }
-
-    /**
-     * {@hide}
-     */
-    public PowerManager(IPowerManager service, Handler handler)
-    {
-        mService = service;
-        mHandler = handler;
-    }
-
-    /**
-     *  TODO: It would be nice to be able to set the poke lock here,
-     *  but I'm not sure what would be acceptable as an interface -
-     *  either a PokeLock object (like WakeLock) or, possibly just a
-     *  method call to set the poke lock. 
-     */
-    
-    IPowerManager mService;
-    Handler mHandler;
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 6ab4dc1..a04ad93 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -116,6 +116,12 @@
     public static final int NFC_UID = 1027;
 
     /**
+     * Defines the UID/GID for the Bluetooth service process.
+     * @hide
+     */
+    public static final int BLUETOOTH_UID = 1002;
+
+    /**
      * Defines the GID for the group that allows write access to the internal media storage.
      * @hide
      */
diff --git a/core/java/android/os/SchedulingPolicyService.java b/core/java/android/os/SchedulingPolicyService.java
index 94f907b..a3fede6 100644
--- a/core/java/android/os/SchedulingPolicyService.java
+++ b/core/java/android/os/SchedulingPolicyService.java
@@ -33,7 +33,7 @@
 
     // Minimum and maximum values allowed for requestPriority parameter prio
     private static final int PRIORITY_MIN = 1;
-    private static final int PRIORITY_MAX = 2;
+    private static final int PRIORITY_MAX = 3;
 
     public SchedulingPolicyService() {
     }
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 7291739..a54c25b 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -46,15 +46,16 @@
  *     such as {@link Thread#sleep(long) Thread.sleep(millls)},
  *     {@link Object#wait(long) Object.wait(millis)}, and
  *     {@link System#nanoTime System.nanoTime()}.  This clock is guaranteed
- *     to be monotonic, and is the recommended basis for the general purpose
- *     interval timing of user interface events, performance measurements,
- *     and anything else that does not need to measure elapsed time during
- *     device sleep.  Most methods that accept a timestamp value expect the
- *     {@link #uptimeMillis} clock.
+ *     to be monotonic, and is suitable for interval timing when the
+ *     interval does not span device sleep.  Most methods that accept a
+ *     timestamp value currently expect the {@link #uptimeMillis} clock.
  *
- *     <li> <p> {@link #elapsedRealtime} is counted in milliseconds since the
- *     system was booted, including deep sleep.  This clock should be used
- *     when measuring time intervals that may span periods of system sleep.
+ *     <li> <p> {@link #elapsedRealtime} and {@link #elapsedRealtimeNano}
+ *     return the time since the system was booted, and include deep sleep.
+ *     This clock is guaranteed to be monotonic, and continues to tick even
+ *     when the CPU is in power saving modes, so is the recommend basis
+ *     for general purpose interval timing.
+ *
  * </ul>
  *
  * There are several mechanisms for controlling the timing of events:
@@ -150,7 +151,14 @@
      * @return elapsed milliseconds since boot.
      */
     native public static long elapsedRealtime();
-    
+
+    /**
+     * Returns nanoseconds since boot, including time spent in sleep.
+     *
+     * @return elapsed nanoseconds since boot.
+     */
+    public static native long elapsedRealtimeNano();
+
     /**
      * Returns milliseconds running in the current thread.
      * 
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index d2050b7..59d0f7a 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -39,11 +39,12 @@
     public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
     public static final long TRACE_TAG_AUDIO = 1L << 8;
     public static final long TRACE_TAG_VIDEO = 1L << 9;
+    public static final long TRACE_TAG_CAMERA = 1L << 10;
 
     public static final int TRACE_FLAGS_START_BIT = 1;
     public static final String[] TRACE_TAGS = {
         "Graphics", "Input", "View", "WebView", "Window Manager",
-        "Activity Manager", "Sync Manager", "Audio", "Video",
+        "Activity Manager", "Sync Manager", "Audio", "Video", "Camera",
     };
 
     public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 74c0a97..840f27d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4276,6 +4276,9 @@
         /** Timeout for package verification. {@hide} */
         public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
 
+        /** Default response code for package verification. {@hide} */
+        public static final String PACKAGE_VERIFIER_DEFAULT_RESPONSE = "verifier_default_response";
+
         /** {@hide} */
         public static final String
                 READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT = "read_external_storage_enforced_default";
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
deleted file mode 100644
index 08a99d2..0000000
--- a/core/java/android/server/BluetoothA2dpService.java
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * TODO: Move this to services.jar
- * and make the constructor package private again.
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothA2dp;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ParcelUuid;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-
-public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
-    private static final String TAG = "BluetoothA2dpService";
-    private static final boolean DBG = true;
-
-    public static final String BLUETOOTH_A2DP_SERVICE = "bluetooth_a2dp";
-
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
-    private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
-
-    private static final String PROPERTY_STATE = "State";
-
-    private final Context mContext;
-    private final IntentFilter mIntentFilter;
-    private HashMap<BluetoothDevice, Integer> mAudioDevices;
-    private final AudioManager mAudioManager;
-    private final BluetoothService mBluetoothService;
-    private final BluetoothAdapter mAdapter;
-    private int   mTargetA2dpState;
-    private BluetoothDevice mPlayingA2dpDevice;
-    private IntentBroadcastHandler mIntentBroadcastHandler;
-    private final WakeLock mWakeLock;
-
-    private static final int MSG_CONNECTION_STATE_CHANGED = 0;
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device =
-                    intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                                               BluetoothAdapter.ERROR);
-                switch (state) {
-                case BluetoothAdapter.STATE_ON:
-                    onBluetoothEnable();
-                    break;
-                case BluetoothAdapter.STATE_TURNING_OFF:
-                    onBluetoothDisable();
-                    break;
-                }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
-                synchronized (this) {
-                    if (mAudioDevices.containsKey(device)) {
-                        int state = mAudioDevices.get(device);
-                        handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
-                    }
-                }
-            } else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
-                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
-                if (streamType == AudioManager.STREAM_MUSIC) {
-                    List<BluetoothDevice> sinks = getConnectedDevices();
-
-                    if (sinks.size() != 0 && isPhoneDocked(sinks.get(0))) {
-                        String address = sinks.get(0).getAddress();
-                        int newVolLevel =
-                          intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
-                        int oldVolLevel =
-                          intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
-                        String path = mBluetoothService.getObjectPathFromAddress(address);
-                        if (newVolLevel > oldVolLevel) {
-                            avrcpVolumeUpNative(path);
-                        } else if (newVolLevel < oldVolLevel) {
-                            avrcpVolumeDownNative(path);
-                        }
-                    }
-                }
-            }
-        }
-    };
-
-    private boolean isPhoneDocked(BluetoothDevice device) {
-        // This works only because these broadcast intents are "sticky"
-        Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
-        if (i != null) {
-            int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                BluetoothDevice dockDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                if (dockDevice != null && device.equals(dockDevice)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {
-        mContext = context;
-
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BluetoothA2dpService");
-
-        mIntentBroadcastHandler = new IntentBroadcastHandler();
-
-        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
-        mBluetoothService = bluetoothService;
-        if (mBluetoothService == null) {
-            throw new RuntimeException("Platform does not support Bluetooth");
-        }
-
-        if (!initNative()) {
-            throw new RuntimeException("Could not init BluetoothA2dpService");
-        }
-
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-
-        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
-        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-        mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
-        mContext.registerReceiver(mReceiver, mIntentFilter);
-
-        mAudioDevices = new HashMap<BluetoothDevice, Integer>();
-
-        if (mBluetoothService.isEnabled())
-            onBluetoothEnable();
-        mTargetA2dpState = -1;
-        mBluetoothService.setA2dpService(this);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private int convertBluezSinkStringToState(String value) {
-        if (value.equalsIgnoreCase("disconnected"))
-            return BluetoothA2dp.STATE_DISCONNECTED;
-        if (value.equalsIgnoreCase("connecting"))
-            return BluetoothA2dp.STATE_CONNECTING;
-        if (value.equalsIgnoreCase("connected"))
-            return BluetoothA2dp.STATE_CONNECTED;
-        if (value.equalsIgnoreCase("playing"))
-            return BluetoothA2dp.STATE_PLAYING;
-        return -1;
-    }
-
-    private boolean isSinkDevice(BluetoothDevice device) {
-        ParcelUuid[] uuids = mBluetoothService.getRemoteUuids(device.getAddress());
-        if (uuids != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
-            return true;
-        }
-        return false;
-    }
-
-    private synchronized void addAudioSink(BluetoothDevice device) {
-        if (mAudioDevices.get(device) == null) {
-            mAudioDevices.put(device, BluetoothA2dp.STATE_DISCONNECTED);
-        }
-    }
-
-    private synchronized void onBluetoothEnable() {
-        String devices = mBluetoothService.getProperty("Devices", true);
-        if (devices != null) {
-            String [] paths = devices.split(",");
-            for (String path: paths) {
-                String address = mBluetoothService.getAddressFromObjectPath(path);
-                BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                ParcelUuid[] remoteUuids = mBluetoothService.getRemoteUuids(address);
-                if (remoteUuids != null)
-                    if (BluetoothUuid.containsAnyUuid(remoteUuids,
-                            new ParcelUuid[] {BluetoothUuid.AudioSink,
-                                                BluetoothUuid.AdvAudioDist})) {
-                        addAudioSink(device);
-                    }
-                }
-        }
-        mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
-        mAudioManager.setParameters("A2dpSuspended=false");
-    }
-
-    private synchronized void onBluetoothDisable() {
-        if (!mAudioDevices.isEmpty()) {
-            BluetoothDevice[] devices = new BluetoothDevice[mAudioDevices.size()];
-            devices = mAudioDevices.keySet().toArray(devices);
-            for (BluetoothDevice device : devices) {
-                int state = getConnectionState(device);
-                switch (state) {
-                    case BluetoothA2dp.STATE_CONNECTING:
-                    case BluetoothA2dp.STATE_CONNECTED:
-                    case BluetoothA2dp.STATE_PLAYING:
-                        disconnectSinkNative(mBluetoothService.getObjectPathFromAddress(
-                                device.getAddress()));
-                        handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
-                        break;
-                    case BluetoothA2dp.STATE_DISCONNECTING:
-                        handleSinkStateChange(device, BluetoothA2dp.STATE_DISCONNECTING,
-                                              BluetoothA2dp.STATE_DISCONNECTED);
-                        break;
-                }
-            }
-            mAudioDevices.clear();
-        }
-
-        mAudioManager.setParameters(BLUETOOTH_ENABLED + "=false");
-    }
-
-    private synchronized boolean isConnectSinkFeasible(BluetoothDevice device) {
-        if (!mBluetoothService.isEnabled() || !isSinkDevice(device) ||
-                getPriority(device) == BluetoothA2dp.PRIORITY_OFF) {
-            return false;
-        }
-
-        addAudioSink(device);
-
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (path == null) {
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean isA2dpPlaying(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-            "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("isA2dpPlaying(" + device + ")");
-        if (device.equals(mPlayingA2dpDevice)) return true;
-        return false;
-    }
-
-    public synchronized boolean connect(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("connectSink(" + device + ")");
-        if (!isConnectSinkFeasible(device)) return false;
-
-        for (BluetoothDevice sinkDevice : mAudioDevices.keySet()) {
-            if (getConnectionState(sinkDevice) != BluetoothProfile.STATE_DISCONNECTED) {
-                disconnect(sinkDevice);
-            }
-        }
-
-        return mBluetoothService.connectSink(device.getAddress());
-    }
-
-    public synchronized boolean connectSinkInternal(BluetoothDevice device) {
-        if (!mBluetoothService.isEnabled()) return false;
-
-        int state = mAudioDevices.get(device);
-
-        // ignore if there are any active sinks
-        if (getDevicesMatchingConnectionStates(new int[] {
-                BluetoothA2dp.STATE_CONNECTING,
-                BluetoothA2dp.STATE_CONNECTED,
-                BluetoothA2dp.STATE_DISCONNECTING}).size() != 0) {
-            return false;
-        }
-
-        switch (state) {
-        case BluetoothA2dp.STATE_CONNECTED:
-        case BluetoothA2dp.STATE_DISCONNECTING:
-            return false;
-        case BluetoothA2dp.STATE_CONNECTING:
-            return true;
-        }
-
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-        // State is DISCONNECTED and we are connecting.
-        if (getPriority(device) < BluetoothA2dp.PRIORITY_AUTO_CONNECT) {
-            setPriority(device, BluetoothA2dp.PRIORITY_AUTO_CONNECT);
-        }
-        handleSinkStateChange(device, state, BluetoothA2dp.STATE_CONNECTING);
-
-        if (!connectSinkNative(path)) {
-            // Restore previous state
-            handleSinkStateChange(device, mAudioDevices.get(device), state);
-            return false;
-        }
-        return true;
-    }
-
-    private synchronized boolean isDisconnectSinkFeasible(BluetoothDevice device) {
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (path == null) {
-            return false;
-        }
-
-        int state = getConnectionState(device);
-        switch (state) {
-        case BluetoothA2dp.STATE_DISCONNECTED:
-        case BluetoothA2dp.STATE_DISCONNECTING:
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean disconnect(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("disconnectSink(" + device + ")");
-        if (!isDisconnectSinkFeasible(device)) return false;
-        return mBluetoothService.disconnectSink(device.getAddress());
-    }
-
-    public synchronized boolean disconnectSinkInternal(BluetoothDevice device) {
-        int state = getConnectionState(device);
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-        switch (state) {
-            case BluetoothA2dp.STATE_DISCONNECTED:
-            case BluetoothA2dp.STATE_DISCONNECTING:
-                return false;
-        }
-        // State is CONNECTING or CONNECTED or PLAYING
-        handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTING);
-        if (!disconnectSinkNative(path)) {
-            // Restore previous state
-            handleSinkStateChange(device, mAudioDevices.get(device), state);
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean suspendSink(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                            "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("suspendSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
-        if (device == null || mAudioDevices == null) {
-            return false;
-        }
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        Integer state = mAudioDevices.get(device);
-        if (path == null || state == null) {
-            return false;
-        }
-
-        mTargetA2dpState = BluetoothA2dp.STATE_CONNECTED;
-        return checkSinkSuspendState(state.intValue());
-    }
-
-    public synchronized boolean resumeSink(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                            "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("resumeSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
-        if (device == null || mAudioDevices == null) {
-            return false;
-        }
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        Integer state = mAudioDevices.get(device);
-        if (path == null || state == null) {
-            return false;
-        }
-        mTargetA2dpState = BluetoothA2dp.STATE_PLAYING;
-        return checkSinkSuspendState(state.intValue());
-    }
-
-    public synchronized int getConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        Integer state = mAudioDevices.get(device);
-        if (state == null)
-            return BluetoothA2dp.STATE_DISCONNECTED;
-        return state;
-    }
-
-    public synchronized List<BluetoothDevice> getConnectedDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        List<BluetoothDevice> sinks = getDevicesMatchingConnectionStates(
-                new int[] {BluetoothA2dp.STATE_CONNECTED});
-        return sinks;
-    }
-
-    public synchronized List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        ArrayList<BluetoothDevice> sinks = new ArrayList<BluetoothDevice>();
-        for (BluetoothDevice device: mAudioDevices.keySet()) {
-            int sinkState = getConnectionState(device);
-            for (int state : states) {
-                if (state == sinkState) {
-                    sinks.add(device);
-                    break;
-                }
-            }
-        }
-        return sinks;
-    }
-
-    public synchronized int getPriority(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
-                BluetoothA2dp.PRIORITY_UNDEFINED);
-    }
-
-    public synchronized boolean setPriority(BluetoothDevice device, int priority) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        return Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), priority);
-    }
-
-    public synchronized boolean allowIncomingConnect(BluetoothDevice device, boolean value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        String address = device.getAddress();
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        Integer data = mBluetoothService.getAuthorizationAgentRequestData(address);
-        if (data == null) {
-            Log.w(TAG, "allowIncomingConnect(" + device + ") called but no native data available");
-            return false;
-        }
-        log("allowIncomingConnect: A2DP: " + device + ":" + value);
-        return mBluetoothService.setAuthorizationNative(address, value, data.intValue());
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.AudioSink.
-     *
-     * @param path the object path for the changed device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private synchronized void onSinkPropertyChanged(String path, String[] propValues) {
-        if (!mBluetoothService.isEnabled()) {
-            return;
-        }
-
-        String name = propValues[0];
-        String address = mBluetoothService.getAddressFromObjectPath(path);
-        if (address == null) {
-            Log.e(TAG, "onSinkPropertyChanged: Address of the remote device in null");
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-
-        if (name.equals(PROPERTY_STATE)) {
-            int state = convertBluezSinkStringToState(propValues[1]);
-            log("A2DP: onSinkPropertyChanged newState is: " + state + "mPlayingA2dpDevice: " + mPlayingA2dpDevice);
-
-            if (mAudioDevices.get(device) == null) {
-                // This is for an incoming connection for a device not known to us.
-                // We have authorized it and bluez state has changed.
-                addAudioSink(device);
-                handleSinkStateChange(device, BluetoothA2dp.STATE_DISCONNECTED, state);
-            } else {
-                if (state == BluetoothA2dp.STATE_PLAYING && mPlayingA2dpDevice == null) {
-                   mPlayingA2dpDevice = device;
-                   handleSinkPlayingStateChange(device, state, BluetoothA2dp.STATE_NOT_PLAYING);
-                } else if (state == BluetoothA2dp.STATE_CONNECTED && mPlayingA2dpDevice != null) {
-                    mPlayingA2dpDevice = null;
-                    handleSinkPlayingStateChange(device, BluetoothA2dp.STATE_NOT_PLAYING,
-                        BluetoothA2dp.STATE_PLAYING);
-                } else {
-                   mPlayingA2dpDevice = null;
-                   int prevState = mAudioDevices.get(device);
-                   handleSinkStateChange(device, prevState, state);
-                }
-            }
-        }
-    }
-
-    private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
-        if (state != prevState) {
-            mAudioDevices.put(device, state);
-
-            checkSinkSuspendState(state);
-            mTargetA2dpState = -1;
-
-            if (getPriority(device) > BluetoothA2dp.PRIORITY_OFF &&
-                    state == BluetoothA2dp.STATE_CONNECTED) {
-                // We have connected or attempting to connect.
-                // Bump priority
-                setPriority(device, BluetoothA2dp.PRIORITY_AUTO_CONNECT);
-                // We will only have 1 device with AUTO_CONNECT priority
-                // To be backward compatible set everyone else to have PRIORITY_ON
-                adjustOtherSinkPriorities(device);
-            }
-
-            int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, state);
-
-            mWakeLock.acquire();
-            mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage(
-                                                            MSG_CONNECTION_STATE_CHANGED,
-                                                            prevState,
-                                                            state,
-                                                            device),
-                                                       delay);
-        }
-    }
-
-    private void handleSinkPlayingStateChange(BluetoothDevice device, int state, int prevState) {
-        Intent intent = new Intent(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
-        if (DBG) log("A2DP Playing state : device: " + device + " State:" + prevState + "->" + state);
-    }
-
-    private void adjustOtherSinkPriorities(BluetoothDevice connectedDevice) {
-        for (BluetoothDevice device : mAdapter.getBondedDevices()) {
-            if (getPriority(device) >= BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
-                !device.equals(connectedDevice)) {
-                setPriority(device, BluetoothA2dp.PRIORITY_ON);
-            }
-        }
-    }
-
-    private boolean checkSinkSuspendState(int state) {
-        boolean result = true;
-
-        if (state != mTargetA2dpState) {
-            if (state == BluetoothA2dp.STATE_PLAYING &&
-                mTargetA2dpState == BluetoothA2dp.STATE_CONNECTED) {
-                mAudioManager.setParameters("A2dpSuspended=true");
-            } else if (state == BluetoothA2dp.STATE_CONNECTED &&
-                mTargetA2dpState == BluetoothA2dp.STATE_PLAYING) {
-                mAudioManager.setParameters("A2dpSuspended=false");
-            } else {
-                result = false;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.AudioSink.
-     *
-     * @param deviceObjectPath the object path for the connecting device
-     * @param result true on success; false on error
-     */
-    private void onConnectSinkResult(String deviceObjectPath, boolean result) {
-        // If the call was a success, ignore we will update the state
-        // when we a Sink Property Change
-        if (!result) {
-            if (deviceObjectPath != null) {
-                String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-                if (address == null) return;
-                BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                int state = getConnectionState(device);
-                handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
-            }
-        }
-    }
-
-    /** Handles A2DP connection state change intent broadcasts. */
-    private class IntentBroadcastHandler extends Handler {
-
-        private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
-            Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
-            intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
-            if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
-
-            mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
-                                                        prevState);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_CONNECTION_STATE_CHANGED:
-                    onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2);
-                    mWakeLock.release();
-                    break;
-            }
-        }
-    }
-
-    @Override
-    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
-        if (mAudioDevices.isEmpty()) return;
-        pw.println("Cached audio devices:");
-        for (BluetoothDevice device : mAudioDevices.keySet()) {
-            int state = mAudioDevices.get(device);
-            pw.println(device + " " + BluetoothA2dp.stateToString(state));
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private native boolean initNative();
-    private native void cleanupNative();
-    private synchronized native boolean connectSinkNative(String path);
-    private synchronized native boolean disconnectSinkNative(String path);
-    private synchronized native boolean suspendSinkNative(String path);
-    private synchronized native boolean resumeSinkNative(String path);
-    private synchronized native Object []getSinkPropertiesNative(String path);
-    private synchronized native boolean avrcpVolumeUpNative(String path);
-    private synchronized native boolean avrcpVolumeDownNative(String path);
-}
diff --git a/core/java/android/server/BluetoothAdapterProperties.java b/core/java/android/server/BluetoothAdapterProperties.java
deleted file mode 100644
index 9723f60..0000000
--- a/core/java/android/server/BluetoothAdapterProperties.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-class BluetoothAdapterProperties {
-
-    private static final String TAG = "BluetoothAdapterProperties";
-
-    private final Map<String, String> mPropertiesMap;
-    private final Context mContext;
-    private final BluetoothService mService;
-
-    BluetoothAdapterProperties(Context context, BluetoothService service) {
-        mPropertiesMap = new HashMap<String, String>();
-        mContext = context;
-        mService = service;
-    }
-
-    synchronized String getProperty(String name) {
-        if (mPropertiesMap.isEmpty()) {
-            getAllProperties();
-        }
-        return mPropertiesMap.get(name);
-    }
-
-    String getObjectPath() {
-        return getProperty("ObjectPath");
-    }
-
-    synchronized void clear() {
-        mPropertiesMap.clear();
-    }
-
-    synchronized boolean isEmpty() {
-        return mPropertiesMap.isEmpty();
-    }
-
-    synchronized void setProperty(String name, String value) {
-        mPropertiesMap.put(name, value);
-    }
-
-    synchronized void getAllProperties() {
-        mContext.enforceCallingOrSelfPermission(
-                BluetoothService.BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        mPropertiesMap.clear();
-
-        String properties[] = (String[]) mService
-                .getAdapterPropertiesNative();
-        // The String Array consists of key-value pairs.
-        if (properties == null) {
-            Log.e(TAG, "*Error*: GetAdapterProperties returned NULL");
-            return;
-        }
-
-        for (int i = 0; i < properties.length; i++) {
-            String name = properties[i];
-            String newValue = null;
-            if (name == null) {
-                Log.e(TAG, "Error:Adapter Property at index " + i + " is null");
-                continue;
-            }
-            if (name.equals("Devices") || name.equals("UUIDs")) {
-                StringBuilder str = new StringBuilder();
-                int len = Integer.valueOf(properties[++i]);
-                for (int j = 0; j < len; j++) {
-                    str.append(properties[++i]);
-                    str.append(",");
-                }
-                if (len > 0) {
-                    newValue = str.toString();
-                }
-            } else {
-                newValue = properties[++i];
-            }
-            mPropertiesMap.put(name, newValue);
-        }
-
-        // Add adapter object path property.
-        String adapterPath = mService.getAdapterPathNative();
-        if (adapterPath != null) {
-            mPropertiesMap.put("ObjectPath", adapterPath + "/dev_");
-        }
-    }
-}
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
deleted file mode 100644
index 1de1839..0000000
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothStateChangeCallback;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.util.IState;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.io.PrintWriter;
-
-/**
- * Bluetooth Adapter StateMachine
- * All the states are at the same level, ie, no hierarchy.
- *                         (BluetootOn)<----------------------<-
- *                           |    ^    -------------------->-  |
- *                           |    |                         |  |
- *            USER_TURN_OFF  |    | SCAN_MODE_CHANGED    m1 |  | USER_TURN_ON
- *         AIRPLANE_MODE_ON  |    |                         |  |
- *                           V    |                         |  |
- *                         (Switching)                   (PerProcessState)
- *                           |    ^                         |  |
- *     POWER_STATE_CHANGED & |    | TURN_ON(_CONTINUE)      |  |
- * ALL_DEVICES_DISCONNECTED  |    |                     m2  |  |
- *                           V    |------------------------<   | SCAN_MODE_CHANGED
- *                          (HotOff)-------------------------->- PER_PROCESS_TURN_ON
- *                           /    ^
- *                          /     |  SERVICE_RECORD_LOADED
- *                         |      |
- *              TURN_COLD  |   (Warmup)
- *                         \      ^
- *                          \     |  TURN_HOT/TURN_ON
- *                           |    |  AIRPLANE_MODE_OFF(when Bluetooth was on before)
- *                           V    |
- *                           (PowerOff)   <----- initial state
- *
- * Legend:
- * m1 = TURN_HOT
- * m2 = Transition to HotOff when number of process wanting BT on is 0.
- *      POWER_STATE_CHANGED will make the transition.
- * Note:
- * The diagram above shows all the states and messages that trigger normal state changes.
- * The diagram above does not capture everything:
- *   The diagram does not capture following messages.
- *   - messages that do not trigger state changes
- *     For example, PER_PROCESS_TURN_ON received in BluetoothOn state
- *   - unhandled messages
- *     For example, USER_TURN_ON received in BluetoothOn state
- *   - timeout messages
- *   The diagram does not capture error conditions and state recoveries.
- *   - For example POWER_STATE_CHANGED received in BluetoothOn state
- */
-final class BluetoothAdapterStateMachine extends StateMachine {
-    private static final String TAG = "BluetoothAdapterStateMachine";
-    private static final boolean DBG = false;
-
-    // Message(what) to take an action
-    //
-    // We get this message when user tries to turn on BT
-    static final int USER_TURN_ON = 1;
-    // We get this message when user tries to turn off BT
-    static final int USER_TURN_OFF = 2;
-    // Per process enable / disable messages
-    static final int PER_PROCESS_TURN_ON = 3;
-    static final int PER_PROCESS_TURN_OFF = 4;
-
-    // Turn on Bluetooth Module, Load firmware, and do all the preparation
-    // needed to get the Bluetooth Module ready but keep it not discoverable
-    // and not connectable. This way the Bluetooth Module can be quickly
-    // switched on if needed
-    static final int TURN_HOT = 5;
-
-    // Message(what) to report a event that the state machine need to respond to
-    //
-    // Event indicates sevice records have been loaded
-    static final int SERVICE_RECORD_LOADED = 51;
-    // Event indicates all the remote Bluetooth devices has been disconnected
-    static final int ALL_DEVICES_DISCONNECTED = 52;
-    // Event indicates the Bluetooth scan mode has changed
-    static final int SCAN_MODE_CHANGED = 53;
-    // Event indicates the powered state has changed
-    static final int POWER_STATE_CHANGED = 54;
-    // Event indicates airplane mode is turned on
-    static final int AIRPLANE_MODE_ON = 55;
-    // Event indicates airplane mode is turned off
-    static final int AIRPLANE_MODE_OFF = 56;
-
-    // private internal messages
-    //
-    // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the
-    // state change intent so that we will not broadcast the intent again in
-    // other state
-    private static final int TURN_ON_CONTINUE = 101;
-    // Unload firmware, turning off Bluetooth module power
-    private static final int TURN_COLD = 102;
-    // Device disconnecting timeout happens
-    private static final int DEVICES_DISCONNECT_TIMEOUT = 103;
-    // Prepare Bluetooth timeout happens
-    private static final int PREPARE_BLUETOOTH_TIMEOUT = 104;
-    // Bluetooth turn off wait timeout happens
-    private static final int TURN_OFF_TIMEOUT = 105;
-    // Bluetooth device power off wait timeout happens
-    private static final int POWER_DOWN_TIMEOUT = 106;
-
-    private Context mContext;
-    private BluetoothService mBluetoothService;
-    private BluetoothEventLoop mEventLoop;
-
-    private BluetoothOn mBluetoothOn;
-    private Switching mSwitching;
-    private HotOff mHotOff;
-    private WarmUp mWarmUp;
-    private PowerOff mPowerOff;
-    private PerProcessState mPerProcessState;
-
-    // this is the BluetoothAdapter state that reported externally
-    private int mPublicState;
-    // When turning off, broadcast STATE_OFF in the last HotOff state
-    // This is because we do HotOff -> PowerOff -> HotOff for USER_TURN_OFF
-    private boolean mDelayBroadcastStateOff;
-
-    // timeout value waiting for all the devices to be disconnected
-    private static final int DEVICES_DISCONNECT_TIMEOUT_TIME = 3000;
-
-    private static final int PREPARE_BLUETOOTH_TIMEOUT_TIME = 10000;
-
-    private static final int TURN_OFF_TIMEOUT_TIME = 5000;
-    private static final int POWER_DOWN_TIMEOUT_TIME = 20;
-
-    BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
-                                 BluetoothAdapter bluetoothAdapter) {
-        super(TAG);
-        mContext = context;
-        mBluetoothService = bluetoothService;
-        mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this);
-
-        mBluetoothOn = new BluetoothOn();
-        mSwitching = new Switching();
-        mHotOff = new HotOff();
-        mWarmUp = new WarmUp();
-        mPowerOff = new PowerOff();
-        mPerProcessState = new PerProcessState();
-
-        addState(mBluetoothOn);
-        addState(mSwitching);
-        addState(mHotOff);
-        addState(mWarmUp);
-        addState(mPowerOff);
-        addState(mPerProcessState);
-
-        setInitialState(mPowerOff);
-        mPublicState = BluetoothAdapter.STATE_OFF;
-        mDelayBroadcastStateOff = false;
-    }
-
-    /**
-     * Bluetooth module's power is off, firmware is not loaded.
-     */
-    private class PowerOff extends State {
-        @Override
-        public void enter() {
-            if (DBG) log("Enter PowerOff: " + getCurrentMessage().what);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("PowerOff process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case USER_TURN_ON:
-                    // starts turning on BT module, broadcast this out
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                    transitionTo(mWarmUp);
-                    if (prepareBluetooth()) {
-                        // this is user request, save the setting
-                        if ((Boolean) message.obj) {
-                            persistSwitchSetting(true);
-                        }
-                        // We will continue turn the BT on all the way to the BluetoothOn state
-                        deferMessage(obtainMessage(TURN_ON_CONTINUE));
-                    } else {
-                        Log.e(TAG, "failed to prepare bluetooth, abort turning on");
-                        transitionTo(mPowerOff);
-                        broadcastState(BluetoothAdapter.STATE_OFF);
-                    }
-                    break;
-                case TURN_HOT:
-                    if (prepareBluetooth()) {
-                        transitionTo(mWarmUp);
-                    }
-                    break;
-                case AIRPLANE_MODE_OFF:
-                    if (getBluetoothPersistedSetting()) {
-                        // starts turning on BT module, broadcast this out
-                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                        transitionTo(mWarmUp);
-                        if (prepareBluetooth()) {
-                            // We will continue turn the BT on all the way to the BluetoothOn state
-                            deferMessage(obtainMessage(TURN_ON_CONTINUE));
-                            transitionTo(mWarmUp);
-                        } else {
-                            Log.e(TAG, "failed to prepare bluetooth, abort turning on");
-                            transitionTo(mPowerOff);
-                            broadcastState(BluetoothAdapter.STATE_OFF);
-                        }
-                    } else if (mContext.getResources().getBoolean
-                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        sendMessage(TURN_HOT);
-                    }
-                    break;
-                case PER_PROCESS_TURN_ON:
-                    if (prepareBluetooth()) {
-                        transitionTo(mWarmUp);
-                    }
-                    deferMessage(obtainMessage(PER_PROCESS_TURN_ON));
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback) message.obj);
-                    break;
-                case USER_TURN_OFF:
-                    Log.w(TAG, "PowerOff received: " + message.what);
-                case AIRPLANE_MODE_ON: // ignore
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-        /**
-         * Turn on Bluetooth Module, Load firmware, and do all the preparation
-         * needed to get the Bluetooth Module ready but keep it not discoverable
-         * and not connectable.
-         * The last step of this method sets up the local service record DB.
-         * There will be a event reporting the status of the SDP setup.
-         */
-        private boolean prepareBluetooth() {
-            if (mBluetoothService.enableNative() != 0) {
-                return false;
-            }
-
-            // try to start event loop, give 2 attempts
-            int retryCount = 2;
-            boolean eventLoopStarted = false;
-            while ((retryCount-- > 0) && !eventLoopStarted) {
-                mEventLoop.start();
-                // it may take a moment for the other thread to do its
-                // thing.  Check periodically for a while.
-                int pollCount = 5;
-                while ((pollCount-- > 0) && !eventLoopStarted) {
-                    if (mEventLoop.isEventLoopRunning()) {
-                        eventLoopStarted = true;
-                        break;
-                    }
-                    try {
-                        Thread.sleep(100);
-                    } catch (InterruptedException e) {
-                        log("prepareBluetooth sleep interrupted: " + pollCount);
-                        break;
-                    }
-                }
-            }
-
-            if (!eventLoopStarted) {
-                mBluetoothService.disableNative();
-                return false;
-            }
-
-            // get BluetoothService ready
-            if (!mBluetoothService.prepareBluetooth()) {
-                mEventLoop.stop();
-                mBluetoothService.disableNative();
-                return false;
-            }
-
-            sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT, PREPARE_BLUETOOTH_TIMEOUT_TIME);
-            return true;
-        }
-    }
-
-    /**
-     * Turning on Bluetooth module's power, loading firmware, starting
-     * event loop thread to listen on Bluetooth module event changes.
-     */
-    private class WarmUp extends State {
-
-        @Override
-        public void enter() {
-            if (DBG) log("Enter WarmUp: " + getCurrentMessage().what);
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("WarmUp process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case SERVICE_RECORD_LOADED:
-                    removeMessages(PREPARE_BLUETOOTH_TIMEOUT);
-                    transitionTo(mHotOff);
-                    if (mDelayBroadcastStateOff) {
-                        broadcastState(BluetoothAdapter.STATE_OFF);
-                        mDelayBroadcastStateOff = false;
-                    }
-                    break;
-                case PREPARE_BLUETOOTH_TIMEOUT:
-                    Log.e(TAG, "Bluetooth adapter SDP failed to load");
-                    shutoffBluetooth();
-                    transitionTo(mPowerOff);
-                    broadcastState(BluetoothAdapter.STATE_OFF);
-                    break;
-                case USER_TURN_ON: // handle this at HotOff state
-                case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth
-                                       // on to the BluetoothOn state
-                case AIRPLANE_MODE_ON:
-                case AIRPLANE_MODE_OFF:
-                case PER_PROCESS_TURN_ON:
-                case PER_PROCESS_TURN_OFF:
-                    deferMessage(message);
-                    break;
-                case USER_TURN_OFF:
-                    Log.w(TAG, "WarmUp received: " + message.what);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-    }
-
-    /**
-     * Bluetooth Module has powered, firmware loaded, event loop started,
-     * SDP loaded, but the modules stays non-discoverable and
-     * non-connectable.
-     */
-    private class HotOff extends State {
-        @Override
-        public void enter() {
-            if (DBG) log("Enter HotOff: " + getCurrentMessage().what);
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("HotOff process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case USER_TURN_ON:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                    if ((Boolean) message.obj) {
-                        persistSwitchSetting(true);
-                    }
-                    // let it fall to TURN_ON_CONTINUE:
-                    //$FALL-THROUGH$
-                case TURN_ON_CONTINUE:
-                    mBluetoothService.switchConnectable(true);
-                    transitionTo(mSwitching);
-                    break;
-                case AIRPLANE_MODE_ON:
-                case TURN_COLD:
-                    shutoffBluetooth();
-                    // we cannot go to power off state yet, we need wait for the Bluetooth
-                    // device power off. Unfortunately the stack does not give a event back
-                    // so we wait a little bit here
-                    sendMessageDelayed(POWER_DOWN_TIMEOUT,
-                                       POWER_DOWN_TIMEOUT_TIME);
-                    break;
-                case POWER_DOWN_TIMEOUT:
-                    transitionTo(mPowerOff);
-                    if (!mDelayBroadcastStateOff) {
-                        broadcastState(BluetoothAdapter.STATE_OFF);
-                    }
-                    break;
-                case AIRPLANE_MODE_OFF:
-                    if (getBluetoothPersistedSetting()) {
-                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                        transitionTo(mSwitching);
-                        mBluetoothService.switchConnectable(true);
-                    }
-                    break;
-                case PER_PROCESS_TURN_ON:
-                    transitionTo(mPerProcessState);
-
-                    // Resend the PER_PROCESS_TURN_ON message so that the callback
-                    // can be sent through.
-                    deferMessage(message);
-
-                    mBluetoothService.switchConnectable(true);
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
-                    break;
-                case USER_TURN_OFF: // ignore
-                    break;
-                case POWER_STATE_CHANGED:
-                    if ((Boolean) message.obj) {
-                        recoverStateMachine(TURN_HOT, null);
-                    }
-                    break;
-                case TURN_HOT:
-                    deferMessage(message);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-    }
-
-    private class Switching extends State {
-
-        @Override
-        public void enter() {
-            if (DBG) log("Enter Switching: " + getCurrentMessage().what);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("Switching process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case SCAN_MODE_CHANGED:
-                    // This event matches mBluetoothService.switchConnectable action
-                    if (mPublicState == BluetoothAdapter.STATE_TURNING_ON) {
-                        // set pairable if it's not
-                        mBluetoothService.setPairable();
-                        mBluetoothService.initBluetoothAfterTurningOn();
-                        transitionTo(mBluetoothOn);
-                        broadcastState(BluetoothAdapter.STATE_ON);
-                        // run bluetooth now that it's turned on
-                        // Note runBluetooth should be called only in adapter STATE_ON
-                        mBluetoothService.runBluetooth();
-                    }
-                    break;
-                case POWER_STATE_CHANGED:
-                    removeMessages(TURN_OFF_TIMEOUT);
-                    if (!((Boolean) message.obj)) {
-                        if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) {
-                            transitionTo(mHotOff);
-                            mBluetoothService.finishDisable();
-                            mBluetoothService.cleanupAfterFinishDisable();
-                            deferMessage(obtainMessage(TURN_COLD));
-                            if (mContext.getResources().getBoolean
-                                (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch) &&
-                                !mBluetoothService.isAirplaneModeOn()) {
-                                deferMessage(obtainMessage(TURN_HOT));
-                                mDelayBroadcastStateOff = true;
-                            }
-                        }
-                    } else {
-                        if (mPublicState != BluetoothAdapter.STATE_TURNING_ON) {
-                            if (mContext.getResources().getBoolean
-                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                                recoverStateMachine(TURN_HOT, null);
-                            } else {
-                                recoverStateMachine(TURN_COLD, null);
-                            }
-                        }
-                    }
-                    break;
-                case ALL_DEVICES_DISCONNECTED:
-                    removeMessages(DEVICES_DISCONNECT_TIMEOUT);
-                    mBluetoothService.switchConnectable(false);
-                    sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    break;
-                case DEVICES_DISCONNECT_TIMEOUT:
-                    sendMessage(ALL_DEVICES_DISCONNECTED);
-                    // reset the hardware for error recovery
-                    Log.e(TAG, "Devices failed to disconnect, reseting...");
-                    deferMessage(obtainMessage(TURN_COLD));
-                    if (mContext.getResources().getBoolean
-                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        deferMessage(obtainMessage(TURN_HOT));
-                    }
-                    break;
-                case TURN_OFF_TIMEOUT:
-                    transitionTo(mHotOff);
-                    finishSwitchingOff();
-                    // reset the hardware for error recovery
-                    Log.e(TAG, "Devices failed to power down, reseting...");
-                    deferMessage(obtainMessage(TURN_COLD));
-                    if (mContext.getResources().getBoolean
-                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        deferMessage(obtainMessage(TURN_HOT));
-                    }
-                    break;
-                case USER_TURN_ON:
-                case AIRPLANE_MODE_OFF:
-                case AIRPLANE_MODE_ON:
-                case PER_PROCESS_TURN_ON:
-                case PER_PROCESS_TURN_OFF:
-                case USER_TURN_OFF:
-                    deferMessage(message);
-                    break;
-
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-    }
-
-    private class BluetoothOn extends State {
-
-        @Override
-        public void enter() {
-            if (DBG) log("Enter BluetoothOn: " + getCurrentMessage().what);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("BluetoothOn process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case USER_TURN_OFF:
-                    if ((Boolean) message.obj) {
-                        persistSwitchSetting(false);
-                    }
-
-                    if (mBluetoothService.isDiscovering()) {
-                        mBluetoothService.cancelDiscovery();
-                    }
-                    if (!mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
-                        transitionTo(mPerProcessState);
-                        deferMessage(obtainMessage(TURN_HOT));
-                        break;
-                    }
-                    //$FALL-THROUGH$ to AIRPLANE_MODE_ON
-                case AIRPLANE_MODE_ON:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
-                    transitionTo(mSwitching);
-                    if (mBluetoothService.getAdapterConnectionState() !=
-                        BluetoothAdapter.STATE_DISCONNECTED) {
-                        mBluetoothService.disconnectDevices();
-                        sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT,
-                                           DEVICES_DISCONNECT_TIMEOUT_TIME);
-                    } else {
-                        mBluetoothService.switchConnectable(false);
-                        sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    }
-
-                    if (message.what == AIRPLANE_MODE_ON || mBluetoothService.isAirplaneModeOn()) {
-                        // We inform all the per process callbacks
-                        allProcessesCallback(false);
-                    }
-                    break;
-                case AIRPLANE_MODE_OFF:
-                case USER_TURN_ON:
-                    Log.w(TAG, "BluetoothOn received: " + message.what);
-                    break;
-                case PER_PROCESS_TURN_ON:
-                    perProcessCallback(true, (IBluetoothStateChangeCallback)message.obj);
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
-                    break;
-                case POWER_STATE_CHANGED:
-                    if ((Boolean) message.obj) {
-                        // reset the state machine and send it TURN_ON_CONTINUE message
-                        recoverStateMachine(USER_TURN_ON, false);
-                    }
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-    }
-
-
-    private class PerProcessState extends State {
-        IBluetoothStateChangeCallback mCallback = null;
-        boolean isTurningOn = false;
-
-        @Override
-        public void enter() {
-            int what = getCurrentMessage().what;
-            if (DBG) log("Enter PerProcessState: " + what);
-
-            if (what == PER_PROCESS_TURN_ON) {
-                isTurningOn = true;
-            } else if (what == USER_TURN_OFF) {
-                isTurningOn = false;
-            } else {
-                Log.e(TAG, "enter PerProcessState: wrong msg: " + what);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("PerProcessState process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch (message.what) {
-                case PER_PROCESS_TURN_ON:
-                    mCallback = (IBluetoothStateChangeCallback)getCurrentMessage().obj;
-
-                    // If this is not the first application call the callback.
-                    if (mBluetoothService.getNumberOfApplicationStateChangeTrackers() > 1) {
-                        perProcessCallback(true, mCallback);
-                    }
-                    break;
-                case SCAN_MODE_CHANGED:
-                    if (isTurningOn) {
-                        perProcessCallback(true, mCallback);
-                        isTurningOn = false;
-                    }
-                    break;
-                case POWER_STATE_CHANGED:
-                    removeMessages(TURN_OFF_TIMEOUT);
-                    if (!((Boolean) message.obj)) {
-                        transitionTo(mHotOff);
-                        if (!mContext.getResources().getBoolean
-                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                            deferMessage(obtainMessage(TURN_COLD));
-                        }
-                    } else {
-                        if (!isTurningOn) {
-                            recoverStateMachine(TURN_COLD, null);
-                            for (IBluetoothStateChangeCallback c:
-                                     mBluetoothService.getApplicationStateChangeCallbacks()) {
-                                perProcessCallback(false, c);
-                                deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c));
-                            }
-                        }
-                    }
-                    break;
-                case TURN_OFF_TIMEOUT:
-                    transitionTo(mHotOff);
-                    Log.e(TAG, "Power-down timed out, resetting...");
-                    deferMessage(obtainMessage(TURN_COLD));
-                    if (mContext.getResources().getBoolean
-                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        deferMessage(obtainMessage(TURN_HOT));
-                    }
-                    break;
-                case USER_TURN_ON:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                    persistSwitchSetting(true);
-                    mBluetoothService.initBluetoothAfterTurningOn();
-                    transitionTo(mBluetoothOn);
-                    broadcastState(BluetoothAdapter.STATE_ON);
-                    // run bluetooth now that it's turned on
-                    mBluetoothService.runBluetooth();
-                    break;
-                case TURN_HOT:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
-                    if (mBluetoothService.getAdapterConnectionState() !=
-                        BluetoothAdapter.STATE_DISCONNECTED) {
-                        mBluetoothService.disconnectDevices();
-                        sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT,
-                                           DEVICES_DISCONNECT_TIMEOUT_TIME);
-                        break;
-                    }
-                    //$FALL-THROUGH$ all devices are already disconnected
-                case ALL_DEVICES_DISCONNECTED:
-                    removeMessages(DEVICES_DISCONNECT_TIMEOUT);
-                    finishSwitchingOff();
-                    break;
-                case DEVICES_DISCONNECT_TIMEOUT:
-                    finishSwitchingOff();
-                    Log.e(TAG, "Devices fail to disconnect, reseting...");
-                    transitionTo(mHotOff);
-                    deferMessage(obtainMessage(TURN_COLD));
-                    for (IBluetoothStateChangeCallback c:
-                             mBluetoothService.getApplicationStateChangeCallbacks()) {
-                        perProcessCallback(false, c);
-                        deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c));
-                    }
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
-                    if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
-                        mBluetoothService.switchConnectable(false);
-                        sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    }
-                    break;
-                case AIRPLANE_MODE_ON:
-                    mBluetoothService.switchConnectable(false);
-                    sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    allProcessesCallback(false);
-                    break;
-                case USER_TURN_OFF:
-                    Log.w(TAG, "PerProcessState received: " + message.what);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-    }
-
-    private void finishSwitchingOff() {
-        mBluetoothService.finishDisable();
-        broadcastState(BluetoothAdapter.STATE_OFF);
-        mBluetoothService.cleanupAfterFinishDisable();
-    }
-
-    private void shutoffBluetooth() {
-        mBluetoothService.shutoffBluetooth();
-        mEventLoop.stop();
-        mBluetoothService.cleanNativeAfterShutoffBluetooth();
-    }
-
-    private void perProcessCallback(boolean on, IBluetoothStateChangeCallback c) {
-        if (c == null) return;
-
-        try {
-            c.onBluetoothStateChange(on);
-        } catch (RemoteException e) {}
-    }
-
-    private void allProcessesCallback(boolean on) {
-        for (IBluetoothStateChangeCallback c:
-             mBluetoothService.getApplicationStateChangeCallbacks()) {
-            perProcessCallback(on, c);
-        }
-        if (!on) {
-            mBluetoothService.clearApplicationStateChangeTracker();
-        }
-    }
-
-    /**
-     * Return the public BluetoothAdapter state
-     */
-    int getBluetoothAdapterState() {
-        return mPublicState;
-    }
-
-    BluetoothEventLoop getBluetoothEventLoop() {
-        return mEventLoop;
-    }
-
-    private void persistSwitchSetting(boolean setOn) {
-        long origCallerIdentityToken = Binder.clearCallingIdentity();
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                               Settings.Secure.BLUETOOTH_ON,
-                               setOn ? 1 : 0);
-        Binder.restoreCallingIdentity(origCallerIdentityToken);
-    }
-
-    private boolean getBluetoothPersistedSetting() {
-        ContentResolver contentResolver = mContext.getContentResolver();
-        return (Settings.Secure.getInt(contentResolver,
-                                       Settings.Secure.BLUETOOTH_ON, 0) > 0);
-    }
-
-    private void broadcastState(int newState) {
-
-        log("Bluetooth state " + mPublicState + " -> " + newState);
-        if (mPublicState == newState) {
-            return;
-        }
-
-        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
-        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState);
-        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mPublicState = newState;
-
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-    }
-
-    /**
-     * bluetoothd has crashed and recovered, the adapter state machine has to
-     * reset itself and try to return to previous state
-     */
-    private void recoverStateMachine(int what, Object obj) {
-        Log.e(TAG, "Get unexpected power on event, reset with: " + what);
-        transitionTo(mHotOff);
-        deferMessage(obtainMessage(TURN_COLD));
-        deferMessage(obtainMessage(what, obj));
-    }
-
-    private void dump(PrintWriter pw) {
-        IState currentState = getCurrentState();
-        if (currentState == mPowerOff) {
-            pw.println("Bluetooth OFF - power down\n");
-        } else if (currentState == mWarmUp) {
-            pw.println("Bluetooth OFF - warm up\n");
-        } else if (currentState == mHotOff) {
-            pw.println("Bluetooth OFF - hot but off\n");
-        } else if (currentState == mSwitching) {
-            pw.println("Bluetooth Switching\n");
-        } else if (currentState == mBluetoothOn) {
-            pw.println("Bluetooth ON\n");
-        } else {
-            pw.println("ERROR: Bluetooth UNKNOWN STATE ");
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
deleted file mode 100644
index 0446f02..0000000
--- a/core/java/android/server/BluetoothBondState.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothHeadset;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Local cache of bonding state.
- * We keep our own state to track the intermediate state BONDING, which
- * bluez does not track.
- * All addresses must be passed in upper case.
- */
-class BluetoothBondState {
-    private static final String TAG = "BluetoothBondState";
-    private static final boolean DBG =  true;
-
-    private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
-    private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
-
-    private static final String AUTO_PAIRING_BLACKLIST =
-        "/etc/bluetooth/auto_pairing.conf";
-    private static final String DYNAMIC_AUTO_PAIRING_BLACKLIST =
-        "/data/misc/bluetooth/dynamic_auto_pairing.conf";
-    private ArrayList<String> mAutoPairingAddressBlacklist;
-    private ArrayList<String> mAutoPairingExactNameBlacklist;
-    private ArrayList<String> mAutoPairingPartialNameBlacklist;
-    private ArrayList<String> mAutoPairingFixedPinZerosKeyboardList;
-    // Addresses added to blacklist dynamically based on usage.
-    private ArrayList<String> mAutoPairingDynamicAddressBlacklist;
-
-    // If this is an outgoing connection, store the address.
-    // There can be only 1 pending outgoing connection at a time,
-    private String mPendingOutgoingBonding;
-
-    private final Context mContext;
-    private final BluetoothService mService;
-    private final BluetoothInputProfileHandler mBluetoothInputProfileHandler;
-    private BluetoothA2dp mA2dpProxy;
-    private BluetoothHeadset mHeadsetProxy;
-
-    private ArrayList<String> mPairingRequestRcvd = new ArrayList<String>();
-
-    BluetoothBondState(Context context, BluetoothService service) {
-        mContext = context;
-        mService = service;
-        mBluetoothInputProfileHandler =
-            BluetoothInputProfileHandler.getInstance(mContext, mService);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        mContext.registerReceiver(mReceiver, filter);
-        readAutoPairingData();
-    }
-
-    synchronized void setPendingOutgoingBonding(String address) {
-        mPendingOutgoingBonding = address;
-    }
-
-    public synchronized String getPendingOutgoingBonding() {
-        return mPendingOutgoingBonding;
-    }
-
-    public synchronized void initBondState() {
-        getProfileProxy();
-        loadBondState();
-    }
-
-    private void loadBondState() {
-        if (mService.getBluetoothStateInternal() !=
-                BluetoothAdapter.STATE_TURNING_ON) {
-            return;
-        }
-        String val = mService.getAdapterProperties().getProperty("Devices");
-        if (val == null) {
-            return;
-        }
-        String[] bonds = val.split(",");
-        if (bonds == null) {
-            return;
-        }
-        mState.clear();
-        if (DBG) Log.d(TAG, "found " + bonds.length + " bonded devices");
-        for (String device : bonds) {
-            mState.put(mService.getAddressFromObjectPath(device).toUpperCase(),
-                    BluetoothDevice.BOND_BONDED);
-        }
-    }
-
-    public synchronized void setBondState(String address, int state) {
-        setBondState(address, state, 0);
-    }
-
-    /** reason is ignored unless state == BOND_NOT_BONDED */
-    public synchronized void setBondState(String address, int state, int reason) {
-        if (DBG) Log.d(TAG, "setBondState " + "address" + " " + state + "reason: " + reason);
-
-        int oldState = getBondState(address);
-        if (oldState == state) {
-            return;
-        }
-
-        // Check if this was a pending outgoing bonding.
-        // If yes, reset the state.
-        if (oldState == BluetoothDevice.BOND_BONDING) {
-            if (address.equals(mPendingOutgoingBonding)) {
-                mPendingOutgoingBonding = null;
-            }
-        }
-
-        if (state == BluetoothDevice.BOND_BONDED) {
-            boolean setTrust = false;
-            if (mPairingRequestRcvd.contains(address)) setTrust = true;
-
-            mService.addProfileState(address, setTrust);
-            mPairingRequestRcvd.remove(address);
-
-        } else if (state == BluetoothDevice.BOND_BONDING) {
-            if (mA2dpProxy == null || mHeadsetProxy == null) {
-                getProfileProxy();
-            }
-        } else if (state == BluetoothDevice.BOND_NONE) {
-            mPairingRequestRcvd.remove(address);
-        }
-
-        setProfilePriorities(address, state);
-
-        if (DBG) {
-            Log.d(TAG, address + " bond state " + oldState + " -> " + state
-                + " (" + reason + ")");
-        }
-        Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mService.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, state);
-        intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
-        if (state == BluetoothDevice.BOND_NONE) {
-            if (reason <= 0) {
-                Log.w(TAG, "setBondState() called to unbond device, but reason code is " +
-                      "invalid. Overriding reason code with BOND_RESULT_REMOVED");
-                reason = BluetoothDevice.UNBOND_REASON_REMOVED;
-            }
-            intent.putExtra(BluetoothDevice.EXTRA_REASON, reason);
-            mState.remove(address);
-        } else {
-            mState.put(address, state);
-        }
-
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-    }
-
-    public boolean isAutoPairingBlacklisted(String address) {
-        if (mAutoPairingAddressBlacklist != null) {
-            for (String blacklistAddress : mAutoPairingAddressBlacklist) {
-                if (address.startsWith(blacklistAddress)) return true;
-            }
-        }
-
-        if (mAutoPairingDynamicAddressBlacklist != null) {
-            for (String blacklistAddress: mAutoPairingDynamicAddressBlacklist) {
-                if (address.equals(blacklistAddress)) return true;
-            }
-        }
-
-        String name = mService.getRemoteName(address);
-        if (name != null) {
-            if (mAutoPairingExactNameBlacklist != null) {
-                for (String blacklistName : mAutoPairingExactNameBlacklist) {
-                    if (name.equals(blacklistName)) return true;
-                }
-            }
-
-            if (mAutoPairingPartialNameBlacklist != null) {
-                for (String blacklistName : mAutoPairingPartialNameBlacklist) {
-                    if (name.startsWith(blacklistName)) return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public boolean isFixedPinZerosAutoPairKeyboard(String address) {
-        // Note: the meaning of blacklist is reversed in this case.
-        // If its in the list, we can go ahead and auto pair since
-        // by default keyboard should have a variable PIN that we don't
-        // auto pair using 0000.
-        if (mAutoPairingFixedPinZerosKeyboardList != null) {
-            for (String blacklistAddress : mAutoPairingFixedPinZerosKeyboardList) {
-                if (address.startsWith(blacklistAddress)) return true;
-            }
-        }
-        return false;
-    }
-
-    public synchronized int getBondState(String address) {
-        Integer state = mState.get(address);
-        if (state == null) {
-            return BluetoothDevice.BOND_NONE;
-        }
-        return state.intValue();
-    }
-
-    /*package*/ synchronized String[] listInState(int state) {
-        ArrayList<String> result = new ArrayList<String>(mState.size());
-        for (Map.Entry<String, Integer> e : mState.entrySet()) {
-            if (e.getValue().intValue() == state) {
-                result.add(e.getKey());
-            }
-        }
-        return result.toArray(new String[result.size()]);
-    }
-
-    public synchronized void addAutoPairingFailure(String address) {
-        if (mAutoPairingDynamicAddressBlacklist == null) {
-            mAutoPairingDynamicAddressBlacklist = new ArrayList<String>();
-        }
-
-        updateAutoPairingData(address);
-        mAutoPairingDynamicAddressBlacklist.add(address);
-    }
-
-    public synchronized boolean isAutoPairingAttemptsInProgress(String address) {
-        return getAttempt(address) != 0;
-    }
-
-    public synchronized void clearPinAttempts(String address) {
-        if (DBG) Log.d(TAG, "clearPinAttempts: " + address);
-
-        mPinAttempt.remove(address);
-    }
-
-    public synchronized boolean hasAutoPairingFailed(String address) {
-        if (mAutoPairingDynamicAddressBlacklist == null) return false;
-
-        return mAutoPairingDynamicAddressBlacklist.contains(address);
-    }
-
-    public synchronized int getAttempt(String address) {
-        Integer attempt = mPinAttempt.get(address);
-        if (attempt == null) {
-            return 0;
-        }
-        return attempt.intValue();
-    }
-
-    public synchronized void attempt(String address) {
-        Integer attempt = mPinAttempt.get(address);
-        int newAttempt;
-        if (attempt == null) {
-            newAttempt = 1;
-        } else {
-            newAttempt = attempt.intValue() + 1;
-        }
-        if (DBG) Log.d(TAG, "attemp newAttempt: " + newAttempt);
-
-        mPinAttempt.put(address, new Integer(newAttempt));
-    }
-
-    private void getProfileProxy() {
-        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
-        if (mA2dpProxy == null) {
-            bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
-                                             BluetoothProfile.A2DP);
-        }
-
-        if (mHeadsetProxy == null) {
-            bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
-                                             BluetoothProfile.HEADSET);
-        }
-    }
-
-    private void closeProfileProxy() {
-        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
-        if (mA2dpProxy != null) {
-            bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dpProxy);
-        }
-
-        if (mHeadsetProxy != null) {
-            bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetProxy);
-        }
-    }
-
-    private BluetoothProfile.ServiceListener mProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dpProxy = (BluetoothA2dp) proxy;
-            } else if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = (BluetoothHeadset) proxy;
-            }
-        }
-
-        public void onServiceDisconnected(int profile) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dpProxy = null;
-            } else if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = null;
-            }
-        }
-    };
-
-    private void copyAutoPairingData() {
-        FileInputStream in = null;
-        FileOutputStream out = null;
-        try {
-            File file = new File(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-            if (file.exists()) return;
-
-            in = new FileInputStream(AUTO_PAIRING_BLACKLIST);
-            out= new FileOutputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-
-            byte[] buf = new byte[1024];
-            int len;
-            while ((len = in.read(buf)) > 0) {
-                out.write(buf, 0, len);
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException: copyAutoPairingData " + e);
-        } catch (IOException e) {
-            Log.e(TAG, "IOException: copyAutoPairingData " + e);
-        } finally {
-             try {
-                 if (in != null) in.close();
-                 if (out != null) out.close();
-             } catch (IOException e) {}
-        }
-    }
-
-    synchronized public void readAutoPairingData() {
-        if (mAutoPairingAddressBlacklist != null) return;
-        copyAutoPairingData();
-        FileInputStream fstream = null;
-        try {
-            fstream = new FileInputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-            DataInputStream in = new DataInputStream(fstream);
-            BufferedReader file = new BufferedReader(new InputStreamReader(in));
-            String line;
-            while((line = file.readLine()) != null) {
-                line = line.trim();
-                if (line.length() == 0 || line.startsWith("//")) continue;
-                String[] value = line.split("=");
-                if (value != null && value.length == 2) {
-                    String[] val = value[1].split(",");
-                    if (value[0].equalsIgnoreCase("AddressBlacklist")) {
-                        mAutoPairingAddressBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("ExactNameBlacklist")) {
-                        mAutoPairingExactNameBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("PartialNameBlacklist")) {
-                        mAutoPairingPartialNameBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("FixedPinZerosKeyboardBlacklist")) {
-                        mAutoPairingFixedPinZerosKeyboardList =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("DynamicAddressBlacklist")) {
-                        mAutoPairingDynamicAddressBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else {
-                        Log.e(TAG, "Error parsing Auto pairing blacklist file");
-                    }
-                }
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException: readAutoPairingData " + e);
-        } catch (IOException e) {
-            Log.e(TAG, "IOException: readAutoPairingData " + e);
-        } finally {
-            if (fstream != null) {
-                try {
-                    fstream.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    // This function adds a bluetooth address to the auto pairing blacklist
-    // file. These addresses are added to DynamicAddressBlacklistSection
-    private void updateAutoPairingData(String address) {
-        BufferedWriter out = null;
-        try {
-            out = new BufferedWriter(new FileWriter(DYNAMIC_AUTO_PAIRING_BLACKLIST, true));
-            StringBuilder str = new StringBuilder();
-            if (mAutoPairingDynamicAddressBlacklist.size() == 0) {
-                str.append("DynamicAddressBlacklist=");
-            }
-            str.append(address);
-            str.append(",");
-            out.write(str.toString());
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException: updateAutoPairingData " + e);
-        } catch (IOException e) {
-            Log.e(TAG, "IOException: updateAutoPairingData " + e);
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    // Set service priority of Hid, A2DP and Headset profiles depending on
-    // the bond state change
-    private void setProfilePriorities(String address, int state) {
-        BluetoothDevice remoteDevice = mService.getRemoteDevice(address);
-        // HID is handled by BluetoothService
-        mBluetoothInputProfileHandler.setInitialInputDevicePriority(remoteDevice, state);
-
-        // Set service priority of A2DP and Headset
-        // We used to do the priority change in the 2 services after the broadcast
-        //   intent reach them. But that left a small time gap that could reject
-        //   incoming connection due to undefined priorities.
-        if (state == BluetoothDevice.BOND_BONDED) {
-            if (mA2dpProxy != null &&
-                  mA2dpProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
-                mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
-            }
-
-            if (mHeadsetProxy != null &&
-                  mHeadsetProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
-                mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
-            }
-        } else if (state == BluetoothDevice.BOND_NONE) {
-            if (mA2dpProxy != null) {
-                mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
-            }
-            if (mHeadsetProxy != null) {
-                mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
-            }
-        }
-
-        if (mA2dpProxy == null || mHeadsetProxy == null) {
-            Log.e(TAG, "Proxy is null:" + mA2dpProxy + ":" + mHeadsetProxy);
-        }
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent == null) return;
-
-            String action = intent.getAction();
-            if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
-                BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                String address = dev.getAddress();
-                mPairingRequestRcvd.add(address);
-            }
-        }
-    };
-}
diff --git a/core/java/android/server/BluetoothDeviceProperties.java b/core/java/android/server/BluetoothDeviceProperties.java
deleted file mode 100644
index fe3ef79..0000000
--- a/core/java/android/server/BluetoothDeviceProperties.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-class BluetoothDeviceProperties {
-
-    private static final String TAG = "BluetoothDeviceProperties";
-
-    private final HashMap<String, Map<String, String>> mPropertiesMap;
-    private final BluetoothService mService;
-
-    BluetoothDeviceProperties(BluetoothService service) {
-        mPropertiesMap = new HashMap<String, Map<String, String>>();
-        mService = service;
-    }
-
-    Map<String, String> addProperties(String address, String[] properties) {
-        /*
-         * We get a DeviceFound signal every time RSSI changes or name changes.
-         * Don't create a new Map object every time.
-         */
-        Map<String, String> propertyValues;
-        synchronized(mPropertiesMap) {
-            propertyValues = mPropertiesMap.get(address);
-            if (propertyValues == null) {
-                propertyValues = new HashMap<String, String>();
-            }
-
-            for (int i = 0; i < properties.length; i++) {
-                String name = properties[i];
-                String newValue = null;
-                int len;
-                if (name == null) {
-                    Log.e(TAG, "Error: Remote Device Property at index "
-                        + i + " is null");
-                    continue;
-                }
-                if (name.equals("UUIDs") || name.equals("Nodes")) {
-                    StringBuilder str = new StringBuilder();
-                    len = Integer.valueOf(properties[++i]);
-                    for (int j = 0; j < len; j++) {
-                        str.append(properties[++i]);
-                        str.append(",");
-                    }
-                    if (len > 0) {
-                        newValue = str.toString();
-                    }
-                } else {
-                    newValue = properties[++i];
-                }
-
-                propertyValues.put(name, newValue);
-            }
-            mPropertiesMap.put(address, propertyValues);
-        }
-
-        // We have added a new remote device or updated its properties.
-        // Also update the serviceChannel cache.
-        mService.updateDeviceServiceChannelCache(address);
-        return propertyValues;
-    }
-
-    void setProperty(String address, String name, String value) {
-        synchronized(mPropertiesMap) {
-            Map <String, String> propVal = mPropertiesMap.get(address);
-            if (propVal != null) {
-                propVal.put(name, value);
-                mPropertiesMap.put(address, propVal);
-            } else {
-                Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
-            }
-        }
-    }
-
-    boolean isInCache(String address) {
-        synchronized (mPropertiesMap) {
-            return (mPropertiesMap.get(address) != null);
-        }
-    }
-
-    boolean isEmpty() {
-        synchronized (mPropertiesMap) {
-            return mPropertiesMap.isEmpty();
-        }
-    }
-
-    Set<String> keySet() {
-        synchronized (mPropertiesMap) {
-            return mPropertiesMap.keySet();
-        }
-    }
-
-    String getProperty(String address, String property) {
-        synchronized(mPropertiesMap) {
-            Map<String, String> properties = mPropertiesMap.get(address);
-            if (properties != null) {
-                return properties.get(property);
-            } else {
-                // Query for remote device properties, again.
-                // We will need to reload the cache when we switch Bluetooth on / off
-                // or if we crash.
-                properties = updateCache(address);
-                if (properties != null) {
-                    return properties.get(property);
-                }
-            }
-        }
-        Log.e(TAG, "getRemoteDeviceProperty: " + property + " not present: " + address);
-        return null;
-    }
-
-    Map<String, String> updateCache(String address) {
-        String[] propValues = mService.getRemoteDeviceProperties(address);
-        if (propValues != null) {
-            return addProperties(address, propValues);
-        }
-        return null;
-    }
-}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
deleted file mode 100644
index b758e7fa..0000000
--- a/core/java/android/server/BluetoothEventLoop.java
+++ /dev/null
@@ -1,1067 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealth;
-import android.bluetooth.BluetoothInputDevice;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothUuid;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ParcelUuid;
-import android.os.PowerManager;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.List;
-
-
-/**
- * @hide
- */
-class BluetoothEventLoop {
-    private static final String TAG = "BluetoothEventLoop";
-    private static final boolean DBG = false;
-
-    private int mNativeData;
-    private Thread mThread;
-    private boolean mStarted;
-    private boolean mInterrupted;
-
-    private final HashMap<String, Integer> mPasskeyAgentRequestData;
-    private final HashMap<String, Integer> mAuthorizationAgentRequestData;
-    private final BluetoothService mBluetoothService;
-    private final BluetoothAdapter mAdapter;
-    private final BluetoothAdapterStateMachine mBluetoothState;
-    private BluetoothA2dp mA2dp;
-    private final Context mContext;
-    // The WakeLock is used for bringing up the LCD during a pairing request
-    // from remote device when Android is in Suspend state.
-    private PowerManager.WakeLock mWakeLock;
-
-    private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 1;
-    private static final int EVENT_AGENT_CANCEL = 2;
-
-    private static final int CREATE_DEVICE_ALREADY_EXISTS = 1;
-    private static final int CREATE_DEVICE_SUCCESS = 0;
-    private static final int CREATE_DEVICE_FAILED = -1;
-
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            String address = null;
-            switch (msg.what) {
-            case EVENT_PAIRING_CONSENT_DELAYED_ACCEPT:
-                address = (String)msg.obj;
-                if (address != null) {
-                    mBluetoothService.setPairingConfirmation(address, true);
-                }
-                break;
-            case EVENT_AGENT_CANCEL:
-                // Set the Bond State to BOND_NONE.
-                // We always have only 1 device in BONDING state.
-                String[] devices = mBluetoothService.listInState(BluetoothDevice.BOND_BONDING);
-                if (devices.length == 0) {
-                    break;
-                } else if (devices.length > 1) {
-                    Log.e(TAG, " There is more than one device in the Bonding State");
-                    break;
-                }
-                address = devices[0];
-                mBluetoothService.setBondState(address,
-                        BluetoothDevice.BOND_NONE,
-                        BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED);
-                break;
-            }
-        }
-    };
-
-    static { classInitNative(); }
-    private static native void classInitNative();
-
-    /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
-                                     BluetoothService bluetoothService,
-                                     BluetoothAdapterStateMachine bluetoothState) {
-        mBluetoothService = bluetoothService;
-        mContext = context;
-        mBluetoothState = bluetoothState;
-        mPasskeyAgentRequestData = new HashMap<String, Integer>();
-        mAuthorizationAgentRequestData = new HashMap<String, Integer>();
-        mAdapter = adapter;
-        //WakeLock instantiation in BluetoothEventLoop class
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
-                | PowerManager.ON_AFTER_RELEASE, TAG);
-        mWakeLock.setReferenceCounted(false);
-        initializeNativeDataNative();
-    }
-
-    /*package*/ void getProfileProxy() {
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
-    }
-
-    private BluetoothProfile.ServiceListener mProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dp = (BluetoothA2dp) proxy;
-            }
-        }
-        public void onServiceDisconnected(int profile) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dp = null;
-            }
-        }
-    };
-
-
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNativeDataNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /* package */ HashMap<String, Integer> getPasskeyAgentRequestData() {
-        return mPasskeyAgentRequestData;
-    }
-
-    /* package */ HashMap<String, Integer> getAuthorizationAgentRequestData() {
-        return mAuthorizationAgentRequestData;
-    }
-
-    /* package */ void start() {
-
-        if (!isEventLoopRunningNative()) {
-            if (DBG) log("Starting Event Loop thread");
-            startEventLoopNative();
-        }
-    }
-
-    public void stop() {
-        if (isEventLoopRunningNative()) {
-            if (DBG) log("Stopping Event Loop thread");
-            stopEventLoopNative();
-        }
-    }
-
-    public boolean isEventLoopRunning() {
-        return isEventLoopRunningNative();
-    }
-
-    private void addDevice(String address, String[] properties) {
-        BluetoothDeviceProperties deviceProperties =
-                mBluetoothService.getDeviceProperties();
-        deviceProperties.addProperties(address, properties);
-        String rssi = deviceProperties.getProperty(address, "RSSI");
-        String classValue = deviceProperties.getProperty(address, "Class");
-        String name = deviceProperties.getProperty(address, "Name");
-        short rssiValue;
-        // For incoming connections, we don't get the RSSI value. Use a default of MIN_VALUE.
-        // If we accept the pairing, we will automatically show it at the top of the list.
-        if (rssi != null) {
-            rssiValue = (short)Integer.valueOf(rssi).intValue();
-        } else {
-            rssiValue = Short.MIN_VALUE;
-        }
-        if (classValue != null) {
-            Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-            intent.putExtra(BluetoothDevice.EXTRA_CLASS,
-                    new BluetoothClass(Integer.valueOf(classValue)));
-            intent.putExtra(BluetoothDevice.EXTRA_RSSI, rssiValue);
-            intent.putExtra(BluetoothDevice.EXTRA_NAME, name);
-
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else {
-            log ("ClassValue: " + classValue + " for remote device: " + address + " is null");
-        }
-    }
-
-    /**
-     * Called by native code on a DeviceFound signal from org.bluez.Adapter.
-     *
-     * @param address the MAC address of the new device
-     * @param properties an array of property keys and value strings
-     *
-     * @see BluetoothDeviceProperties#addProperties(String, String[])
-     */
-    private void onDeviceFound(String address, String[] properties) {
-        if (properties == null) {
-            Log.e(TAG, "ERROR: Remote device properties are null");
-            return;
-        }
-        addDevice(address, properties);
-    }
-
-    /**
-     * Called by native code on a DeviceDisappeared signal from
-     * org.bluez.Adapter.
-     *
-     * @param address the MAC address of the disappeared device
-     */
-    private void onDeviceDisappeared(String address) {
-        Intent intent = new Intent(BluetoothDevice.ACTION_DISAPPEARED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
-    /**
-     * Called by native code on a DisconnectRequested signal from
-     * org.bluez.Device.
-     *
-     * @param deviceObjectPath the object path for the disconnecting device
-     */
-    private void onDeviceDisconnectRequested(String deviceObjectPath) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onDeviceDisconnectRequested: Address of the remote device in null");
-            return;
-        }
-        Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
-    /**
-     * Called by native code for the async response to a CreatePairedDevice
-     * method call to org.bluez.Adapter.
-     *
-     * @param address the MAC address of the device to pair
-     * @param result success or error result for the pairing operation
-     */
-    private void onCreatePairedDeviceResult(String address, int result) {
-        address = address.toUpperCase();
-        mBluetoothService.onCreatePairedDeviceResult(address, result);
-    }
-
-    /**
-     * Called by native code on a DeviceCreated signal from org.bluez.Adapter.
-     *
-     * @param deviceObjectPath the object path for the created device
-     */
-    private void onDeviceCreated(String deviceObjectPath) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onDeviceCreated: device address null!" + " deviceObjectPath: " +
-                  deviceObjectPath);
-            return;
-        }
-        if (!mBluetoothService.isRemoteDeviceInCache(address)) {
-            // Incoming connection, we haven't seen this device, add to cache.
-            String[] properties = mBluetoothService.getRemoteDeviceProperties(address);
-            if (properties != null) {
-                addDevice(address, properties);
-            }
-        }
-    }
-
-    /**
-     * Called by native code on a DeviceRemoved signal from org.bluez.Adapter.
-     *
-     * @param deviceObjectPath the object path for the removed device
-     */
-    private void onDeviceRemoved(String deviceObjectPath) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address != null) {
-            mBluetoothService.setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE,
-                BluetoothDevice.UNBOND_REASON_REMOVED);
-            mBluetoothService.setRemoteDeviceProperty(address, "UUIDs", null);
-        }
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Adapter. This method is also called from
-     * {@link BluetoothAdapterStateMachine} to set the "Pairable"
-     * property when Bluetooth is enabled.
-     *
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    /*package*/ void onPropertyChanged(String[] propValues) {
-        BluetoothAdapterProperties adapterProperties =
-                mBluetoothService.getAdapterProperties();
-
-        if (adapterProperties.isEmpty()) {
-            // We have got a property change before
-            // we filled up our cache.
-            adapterProperties.getAllProperties();
-        }
-        log("Property Changed: " + propValues[0] + " : " + propValues[1]);
-        String name = propValues[0];
-        if (name.equals("Name")) {
-            adapterProperties.setProperty(name, propValues[1]);
-            Intent intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
-            intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, propValues[1]);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Pairable") || name.equals("Discoverable")) {
-            adapterProperties.setProperty(name, propValues[1]);
-
-            if (name.equals("Discoverable")) {
-                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);
-            }
-
-            String pairable = name.equals("Pairable") ? propValues[1] :
-                adapterProperties.getProperty("Pairable");
-            String discoverable = name.equals("Discoverable") ? propValues[1] :
-                adapterProperties.getProperty("Discoverable");
-
-            // This shouldn't happen, unless Adapter Properties are null.
-            if (pairable == null || discoverable == null)
-                return;
-
-            int mode = BluetoothService.bluezStringToScanMode(
-                    pairable.equals("true"),
-                    discoverable.equals("true"));
-            if (mode >= 0) {
-                Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-                intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mode);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-            }
-        } else if (name.equals("Discovering")) {
-            Intent intent;
-            adapterProperties.setProperty(name, propValues[1]);
-            if (propValues[1].equals("true")) {
-                intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
-            } else {
-                // Stop the discovery.
-                mBluetoothService.cancelDiscovery();
-                intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
-            }
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Devices") || name.equals("UUIDs")) {
-            String value = null;
-            int len = Integer.valueOf(propValues[1]);
-            if (len > 0) {
-                StringBuilder str = new StringBuilder();
-                for (int i = 2; i < propValues.length; i++) {
-                    str.append(propValues[i]);
-                    str.append(",");
-                }
-                value = str.toString();
-            }
-            adapterProperties.setProperty(name, value);
-            if (name.equals("UUIDs")) {
-                mBluetoothService.updateBluetoothState(value);
-            }
-        } else if (name.equals("Powered")) {
-            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED,
-                propValues[1].equals("true") ? new Boolean(true) : new Boolean(false));
-        } else if (name.equals("DiscoverableTimeout")) {
-            adapterProperties.setProperty(name, propValues[1]);
-        }
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Device.
-     *
-     * @param deviceObjectPath the object path for the changed device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private void onDevicePropertyChanged(String deviceObjectPath, String[] propValues) {
-        String name = propValues[0];
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null");
-            return;
-        }
-        log("Device property changed: " + address + " property: "
-            + name + " value: " + propValues[1]);
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        if (name.equals("Name")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothDevice.EXTRA_NAME, propValues[1]);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Alias")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = new Intent(BluetoothDevice.ACTION_ALIAS_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Class")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothDevice.EXTRA_CLASS,
-                    new BluetoothClass(Integer.valueOf(propValues[1])));
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Connected")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = null;
-            if (propValues[1].equals("true")) {
-                intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED);
-                // Set the link timeout to 8000 slots (5 sec timeout)
-                // for bluetooth docks.
-                if (mBluetoothService.isBluetoothDock(address)) {
-                    mBluetoothService.setLinkTimeout(address, 8000);
-                }
-            } else {
-                intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-            }
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("UUIDs")) {
-            String uuid = null;
-            int len = Integer.valueOf(propValues[1]);
-            if (len > 0) {
-                StringBuilder str = new StringBuilder();
-                for (int i = 2; i < propValues.length; i++) {
-                    str.append(propValues[i]);
-                    str.append(",");
-                }
-                uuid = str.toString();
-            }
-            mBluetoothService.setRemoteDeviceProperty(address, name, uuid);
-
-            // UUIDs have changed, query remote service channel and update cache.
-            mBluetoothService.updateDeviceServiceChannelCache(address);
-
-            mBluetoothService.sendUuidIntent(address);
-        } else if (name.equals("Paired")) {
-            if (propValues[1].equals("true")) {
-                // If locally initiated pairing, we will
-                // not go to BOND_BONDED state until we have received a
-                // successful return value in onCreatePairedDeviceResult
-                if (null == mBluetoothService.getPendingOutgoingBonding()) {
-                    mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDED);
-                }
-            } else {
-                mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE);
-                mBluetoothService.setRemoteDeviceProperty(address, "Trusted", "false");
-            }
-        } else if (name.equals("Trusted")) {
-            if (DBG)
-                log("set trust state succeeded, value is: " + propValues[1]);
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-        }
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Input.
-     *
-     * @param path the object path for the changed input device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private void onInputDevicePropertyChanged(String path, String[] propValues) {
-        String address = mBluetoothService.getAddressFromObjectPath(path);
-        if (address == null) {
-            Log.e(TAG, "onInputDevicePropertyChanged: Address of the remote device is null");
-            return;
-        }
-        log("Input Device : Name of Property is: " + propValues[0]);
-        boolean state = false;
-        if (propValues[1].equals("true")) {
-            state = true;
-        }
-        mBluetoothService.handleInputDevicePropertyChange(address, state);
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Network.
-     *
-     * @param deviceObjectPath the object path for the changed PAN device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private void onPanDevicePropertyChanged(String deviceObjectPath, String[] propValues) {
-        String name = propValues[0];
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onPanDevicePropertyChanged: Address of the remote device in null");
-            return;
-        }
-        if (DBG) {
-            log("Pan Device property changed: " + address + "  property: "
-                    + name + " value: "+ propValues[1]);
-        }
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        if (name.equals("Connected")) {
-            if (propValues[1].equals("false")) {
-                mBluetoothService.handlePanDeviceStateChange(device,
-                                          BluetoothPan.STATE_DISCONNECTED,
-                                          BluetoothPan.LOCAL_PANU_ROLE);
-            }
-        } else if (name.equals("Interface")) {
-            String iface = propValues[1];
-            if (!iface.equals("")) {
-                mBluetoothService.handlePanDeviceStateChange(device, iface,
-                                              BluetoothPan.STATE_CONNECTED,
-                                              BluetoothPan.LOCAL_PANU_ROLE);
-            }
-        }
-    }
-
-    private String checkPairingRequestAndGetAddress(String objectPath, int nativeData) {
-        String address = mBluetoothService.getAddressFromObjectPath(objectPath);
-        if (address == null) {
-            Log.e(TAG, "Unable to get device address in checkPairingRequestAndGetAddress, " +
-                  "returning null");
-            return null;
-        }
-        address = address.toUpperCase();
-        mPasskeyAgentRequestData.put(address, new Integer(nativeData));
-
-        if (mBluetoothService.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF) {
-            // shutdown path
-            mBluetoothService.cancelPairingUserInput(address);
-            return null;
-        }
-        // Set state to BONDING. For incoming connections it will be set here.
-        // For outgoing connections, it gets set when we call createBond.
-        // Also set it only when the state is not already Bonded, we can sometimes
-        // get an authorization request from the remote end if it doesn't have the link key
-        // while we still have it.
-        if (mBluetoothService.getBondState(address) != BluetoothDevice.BOND_BONDED)
-            mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDING);
-        return address;
-    }
-
-    /**
-     * Called by native code on a RequestPairingConsent method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device to request pairing consent for
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPairingConsent(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        /* The link key will not be stored if the incoming request has MITM
-         * protection switched on. Unfortunately, some devices have MITM
-         * switched on even though their capabilities are NoInputNoOutput,
-         * so we may get this request many times. Also if we respond immediately,
-         * the other end is unable to handle it. Delay sending the message.
-         */
-        if (mBluetoothService.getBondState(address) == BluetoothDevice.BOND_BONDED) {
-            Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT);
-            message.obj = address;
-            mHandler.sendMessageDelayed(message, 1500);
-            return;
-        }
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                        BluetoothDevice.PAIRING_VARIANT_CONSENT);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a RequestConfirmation method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device to confirm the passkey for
-     * @param passkey an integer containing the 6-digit passkey to confirm
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPasskeyConfirmation(String objectPath, int passkey, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a RequestPasskey method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting a passkey
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPasskey(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_PASSKEY);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a RequestPinCode method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting a PIN code
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPinCode(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        String pendingOutgoingAddress =
-                mBluetoothService.getPendingOutgoingBonding();
-        BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address));
-        int btDeviceClass = btClass.getDeviceClass();
-
-        if (address.equals(pendingOutgoingAddress)) {
-            // we initiated the bonding
-
-            // Check if its a dock
-            if (mBluetoothService.isBluetoothDock(address)) {
-                String pin = mBluetoothService.getDockPin();
-                mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes(pin));
-                return;
-            }
-
-            // try 0000 once if the device looks dumb
-            switch (btDeviceClass) {
-            case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
-            case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
-            case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
-            case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
-            case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
-                if (mBluetoothService.attemptAutoPair(address)) return;
-           }
-        }
-
-        if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD ||
-            btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) {
-            // Its a keyboard. Follow the HID spec recommendation of creating the
-            // passkey and displaying it to the user. If the keyboard doesn't follow
-            // the spec recommendation, check if the keyboard has a fixed PIN zero
-            // and pair.
-            if (mBluetoothService.isFixedPinZerosAutoPairKeyboard(address)) {
-                mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
-                return;
-            }
-
-            // Generate a variable PIN. This is not truly random but good enough.
-            int pin = (int) Math.floor(Math.random() * 10000);
-            sendDisplayPinIntent(address, pin);
-            return;
-        }
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PIN);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a DisplayPasskey method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device to display the passkey for
-     * @param passkey an integer containing the 6-digit passkey
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onDisplayPasskey(String objectPath, int passkey, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                        BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        //Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-    }
-
-    private void sendDisplayPinIntent(String address, int pin) {
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin);
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                        BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        //Release wakelock to allow the LCD to go off after the PIN popup notifcation.
-        mWakeLock.release();
-    }
-
-    /**
-     * Called by native code on a RequestOobData method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting OOB data
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestOobData(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
-    /**
-     * Called by native code on an Authorize method call to org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting to be authorized
-     * @param deviceUuid the UUID of the requesting device
-     * @param nativeData reference for native data
-     */
-    private void  onAgentAuthorize(String objectPath, String deviceUuid, int nativeData) {
-        if (!mBluetoothService.isEnabled()) return;
-
-        String address = mBluetoothService.getAddressFromObjectPath(objectPath);
-        if (address == null) {
-            Log.e(TAG, "Unable to get device address in onAuthAgentAuthorize");
-            return;
-        }
-
-        boolean authorized = false;
-        ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mAuthorizationAgentRequestData.put(address, new Integer(nativeData));
-
-        // Bluez sends the UUID of the local service being accessed, _not_ the
-        // remote service
-        if (mA2dp != null &&
-            (BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid)
-              || BluetoothUuid.isAdvAudioDist(uuid)) &&
-              !isOtherSinkInNonDisconnectedState(address)) {
-            authorized = mA2dp.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
-            if (authorized && !BluetoothUuid.isAvrcpTarget(uuid)) {
-                Log.i(TAG, "First check pass for incoming A2DP / AVRCP connection from " + address);
-                // Some headsets try to connect AVCTP before AVDTP - against the recommendation
-                // If AVCTP connection fails, we get stuck in IncomingA2DP state in the state
-                // machine.  We don't handle AVCTP signals currently. We only send
-                // intents for AVDTP state changes. We need to handle both of them in
-                // some cases. For now, just don't move to incoming state in this case.
-                mBluetoothService.notifyIncomingA2dpConnection(address, false);
-            } else {
-                Log.i(TAG, "" + authorized +
-                      "Incoming A2DP / AVRCP connection from " + address);
-                mA2dp.allowIncomingConnect(device, authorized);
-                mBluetoothService.notifyIncomingA2dpConnection(address, true);
-            }
-        } else if (BluetoothUuid.isInputDevice(uuid)) {
-            // We can have more than 1 input device connected.
-            authorized = mBluetoothService.getInputDevicePriority(device) >
-                    BluetoothInputDevice.PRIORITY_OFF;
-            if (authorized) {
-                Log.i(TAG, "First check pass for incoming HID connection from " + address);
-                // notify profile state change
-                mBluetoothService.notifyIncomingHidConnection(address);
-            } else {
-                Log.i(TAG, "Rejecting incoming HID connection from " + address);
-                mBluetoothService.allowIncomingProfileConnect(device, authorized);
-            }
-        } else if (BluetoothUuid.isBnep(uuid)) {
-            // PAN doesn't go to the state machine, accept or reject from here
-            authorized = mBluetoothService.allowIncomingTethering();
-            mBluetoothService.allowIncomingProfileConnect(device, authorized);
-        } else {
-            Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
-            mBluetoothService.allowIncomingProfileConnect(device, authorized);
-        }
-        log("onAgentAuthorize(" + objectPath + ", " + deviceUuid + ") = " + authorized);
-    }
-
-    private boolean onAgentOutOfBandDataAvailable(String objectPath) {
-        if (!mBluetoothService.isEnabled()) return false;
-
-        String address = mBluetoothService.getAddressFromObjectPath(objectPath);
-        if (address == null) return false;
-
-        if (mBluetoothService.getDeviceOutOfBandData(
-            mAdapter.getRemoteDevice(address)) != null) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean isOtherSinkInNonDisconnectedState(String address) {
-        List<BluetoothDevice> devices =
-            mA2dp.getDevicesMatchingConnectionStates(new int[] {BluetoothA2dp.STATE_CONNECTED,
-                                                     BluetoothA2dp.STATE_CONNECTING,
-                                                     BluetoothA2dp.STATE_DISCONNECTING});
-
-        if (devices.size() == 0) return false;
-        for (BluetoothDevice dev: devices) {
-            if (!dev.getAddress().equals(address)) return true;
-        }
-        return false;
-    }
-
-    /**
-     * Called by native code on a Cancel method call to org.bluez.Agent.
-     */
-    private void onAgentCancel() {
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_AGENT_CANCEL),
-                   1500);
-
-        return;
-    }
-
-    /**
-     * Called by native code for the async response to a DiscoverServices
-     * method call to org.bluez.Adapter.
-     *
-     * @param deviceObjectPath the path for the specified device
-     * @param result true for success; false on error
-     */
-    private void onDiscoverServicesResult(String deviceObjectPath, boolean result) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) return;
-
-        // We don't parse the xml here, instead just query Bluez for the properties.
-        if (result) {
-            mBluetoothService.updateRemoteDevicePropertiesCache(address);
-        }
-        mBluetoothService.sendUuidIntent(address);
-        mBluetoothService.makeServiceChannelCallbacks(address);
-    }
-
-    /**
-     * Called by native code for the async response to a CreateDevice
-     * method call to org.bluez.Adapter.
-     *
-     * @param address the MAC address of the device to create
-     * @param result {@link #CREATE_DEVICE_SUCCESS},
-     *  {@link #CREATE_DEVICE_ALREADY_EXISTS} or {@link #CREATE_DEVICE_FAILED}}
-     */
-    private void onCreateDeviceResult(String address, int result) {
-        if (DBG) log("Result of onCreateDeviceResult:" + result);
-
-        switch (result) {
-        case CREATE_DEVICE_ALREADY_EXISTS:
-            String path = mBluetoothService.getObjectPathFromAddress(address);
-            if (path != null) {
-                mBluetoothService.discoverServicesNative(path, "");
-                break;
-            }
-            Log.w(TAG, "Device exists, but we don't have the bluez path, failing");
-            // fall-through
-        case CREATE_DEVICE_FAILED:
-            mBluetoothService.sendUuidIntent(address);
-            mBluetoothService.makeServiceChannelCallbacks(address);
-            break;
-        case CREATE_DEVICE_SUCCESS:
-            // nothing to do, UUID intent's will be sent via property changed
-        }
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.Input.
-     *
-     * @param path the path of the specified input device
-     * @param result Result code of the operation.
-     */
-    private void onInputDeviceConnectionResult(String path, int result) {
-        // Success case gets handled by Property Change signal
-        if (result != BluetoothInputDevice.INPUT_OPERATION_SUCCESS) {
-            String address = mBluetoothService.getAddressFromObjectPath(path);
-            if (address == null) return;
-
-            boolean connected = false;
-            BluetoothDevice device = mAdapter.getRemoteDevice(address);
-            int state = mBluetoothService.getInputDeviceConnectionState(device);
-            if (state == BluetoothInputDevice.STATE_CONNECTING) {
-                if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) {
-                    connected = true;
-                } else {
-                    connected = false;
-                }
-            } else if (state == BluetoothInputDevice.STATE_DISCONNECTING) {
-                if (result == BluetoothInputDevice.INPUT_DISCONNECT_FAILED_NOT_CONNECTED) {
-                    connected = false;
-                } else {
-                    // There is no better way to handle this, this shouldn't happen
-                    connected = true;
-                }
-            } else {
-                Log.e(TAG, "Error onInputDeviceConnectionResult. State is:" + state);
-            }
-            mBluetoothService.handleInputDevicePropertyChange(address, connected);
-        }
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.Network.
-     *
-     * @param path the path of the specified PAN device
-     * @param result Result code of the operation.
-     */
-    private void onPanDeviceConnectionResult(String path, int result) {
-        log ("onPanDeviceConnectionResult " + path + " " + result);
-        // Success case gets handled by Property Change signal
-        if (result != BluetoothPan.PAN_OPERATION_SUCCESS) {
-            String address = mBluetoothService.getAddressFromObjectPath(path);
-            if (address == null) return;
-
-            boolean connected = false;
-            BluetoothDevice device = mAdapter.getRemoteDevice(address);
-            int state = mBluetoothService.getPanDeviceConnectionState(device);
-            if (state == BluetoothPan.STATE_CONNECTING) {
-                if (result == BluetoothPan.PAN_CONNECT_FAILED_ALREADY_CONNECTED) {
-                    connected = true;
-                } else {
-                    connected = false;
-                }
-            } else if (state == BluetoothPan.STATE_DISCONNECTING) {
-                if (result == BluetoothPan.PAN_DISCONNECT_FAILED_NOT_CONNECTED) {
-                    connected = false;
-                } else {
-                    // There is no better way to handle this, this shouldn't happen
-                    connected = true;
-                }
-            } else {
-                Log.e(TAG, "Error onPanDeviceConnectionResult. State is: "
-                        + state + " result: "+ result);
-            }
-            int newState = connected? BluetoothPan.STATE_CONNECTED :
-                BluetoothPan.STATE_DISCONNECTED;
-            mBluetoothService.handlePanDeviceStateChange(device, newState,
-                                                  BluetoothPan.LOCAL_PANU_ROLE);
-        }
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.Health
-     *
-     * @param chanCode The internal id of the channel
-     * @param result Result code of the operation.
-     */
-    private void onHealthDeviceConnectionResult(int chanCode, int result) {
-        log ("onHealthDeviceConnectionResult " + chanCode + " " + result);
-        // Success case gets handled by Property Change signal
-        if (result != BluetoothHealth.HEALTH_OPERATION_SUCCESS) {
-            mBluetoothService.onHealthDeviceChannelConnectionError(chanCode,
-                                                 BluetoothHealth.STATE_CHANNEL_DISCONNECTED);
-        }
-    }
-
-    /**
-     * Called by native code on a DeviceDisconnected signal from
-     * org.bluez.NetworkServer.
-     *
-     * @param address the MAC address of the disconnected device
-     */
-    private void onNetworkDeviceDisconnected(String address) {
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
-                                                      BluetoothPan.LOCAL_NAP_ROLE);
-    }
-
-    /**
-     * Called by native code on a DeviceConnected signal from
-     * org.bluez.NetworkServer.
-     *
-     * @param address the MAC address of the connected device
-     * @param iface interface of remote network
-     * @param destUuid unused UUID parameter
-     */
-    private void onNetworkDeviceConnected(String address, String iface, int destUuid) {
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED,
-                                                      BluetoothPan.LOCAL_NAP_ROLE);
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.HealthDevice.
-     *
-     * @param devicePath the object path of the remote device
-     * @param propValues Properties (Name-Value) of the Health Device.
-     */
-    private void onHealthDevicePropertyChanged(String devicePath, String[] propValues) {
-        log("Health Device : Name of Property is: " + propValues[0] + " Value:" + propValues[1]);
-        mBluetoothService.onHealthDevicePropertyChanged(devicePath, propValues[1]);
-    }
-
-    /**
-     * Called by native code on a ChannelCreated/Deleted signal from
-     * org.bluez.HealthDevice.
-     *
-     * @param devicePath the object path of the remote device
-     * @param channelPath the path of the health channel.
-     * @param exists Boolean to indicate if the channel was created or deleted.
-     */
-    private void onHealthDeviceChannelChanged(String devicePath, String channelPath,
-            boolean exists) {
-        log("Health Device : devicePath: " + devicePath + ":channelPath:" + channelPath +
-                ":exists" + exists);
-        mBluetoothService.onHealthDeviceChannelChanged(devicePath, channelPath, exists);
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private native void initializeNativeDataNative();
-    private native void startEventLoopNative();
-    private native void stopEventLoopNative();
-    private native boolean isEventLoopRunningNative();
-    private native void cleanupNativeDataNative();
-}
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
deleted file mode 100644
index 5e93b81..0000000
--- a/core/java/android/server/BluetoothHealthProfileHandler.java
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealth;
-import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.IBluetoothHealthCallback;
-import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * This handles all the operations on the Bluetooth Health profile.
- * All functions are called by BluetoothService, as Bluetooth Service
- * is the Service handler for the HDP profile.
- *
- * @hide
- */
-final class BluetoothHealthProfileHandler {
-    private static final String TAG = "BluetoothHealthProfileHandler";
-    private static final boolean DBG = false;
-
-    private static BluetoothHealthProfileHandler sInstance;
-    private BluetoothService mBluetoothService;
-    private ArrayList<HealthChannel> mHealthChannels;
-    private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
-    private HashMap <BluetoothDevice, Integer> mHealthDevices;
-    private HashMap <BluetoothHealthAppConfiguration, IBluetoothHealthCallback> mCallbacks;
-
-    private static final int MESSAGE_REGISTER_APPLICATION = 0;
-    private static final int MESSAGE_UNREGISTER_APPLICATION = 1;
-    private static final int MESSAGE_CONNECT_CHANNEL = 2;
-    private static final AtomicInteger sChannelId = new AtomicInteger();
-
-    class HealthChannel {
-        private ParcelFileDescriptor mChannelFd;
-        private boolean mMainChannel;
-        private String mChannelPath;
-        private BluetoothDevice mDevice;
-        private BluetoothHealthAppConfiguration mConfig;
-        private int mState;
-        private int mChannelType;
-        private int mId;
-
-        HealthChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config,
-                ParcelFileDescriptor fd, boolean mainChannel, String channelPath) {
-             mChannelFd = fd;
-             mMainChannel = mainChannel;
-             mChannelPath = channelPath;
-             mDevice = device;
-             mConfig = config;
-             mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-             mId = getChannelId();
-        }
-    }
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MESSAGE_REGISTER_APPLICATION:
-                BluetoothHealthAppConfiguration registerApp =
-                    (BluetoothHealthAppConfiguration) msg.obj;
-                int role = registerApp.getRole();
-                String path = null;
-
-                if (role == BluetoothHealth.SINK_ROLE) {
-                    path = mBluetoothService.registerHealthApplicationNative(
-                            registerApp.getDataType(), getStringRole(role), registerApp.getName());
-                } else {
-                    path = mBluetoothService.registerHealthApplicationNative(
-                            registerApp.getDataType(), getStringRole(role), registerApp.getName(),
-                            getStringChannelType(registerApp.getChannelType()));
-                }
-
-                if (path == null) {
-                    callHealthApplicationStatusCallback(registerApp,
-                            BluetoothHealth.APP_CONFIG_REGISTRATION_FAILURE);
-                    mCallbacks.remove(registerApp);
-                } else {
-                    mHealthAppConfigs.put(registerApp, path);
-                    callHealthApplicationStatusCallback(registerApp,
-                            BluetoothHealth.APP_CONFIG_REGISTRATION_SUCCESS);
-                }
-
-                break;
-            case MESSAGE_UNREGISTER_APPLICATION:
-                BluetoothHealthAppConfiguration unregisterApp =
-                    (BluetoothHealthAppConfiguration) msg.obj;
-
-                // Disconnect all the channels
-                for (HealthChannel chan : mHealthChannels) {
-                    if (chan.mConfig.equals(unregisterApp) &&
-                            chan.mState != BluetoothHealth.STATE_CHANNEL_DISCONNECTED) {
-                        disconnectChannel(chan.mDevice, unregisterApp, chan.mId);
-                    }
-                }
-
-                boolean result = mBluetoothService.unregisterHealthApplicationNative(
-                        mHealthAppConfigs.get(unregisterApp));
-                if (result) {
-                    callHealthApplicationStatusCallback(unregisterApp,
-                            BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS);
-                    mCallbacks.remove(unregisterApp);
-                    mHealthAppConfigs.remove(unregisterApp);
-                } else {
-                    callHealthApplicationStatusCallback(unregisterApp,
-                            BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE);
-                }
-                break;
-            case MESSAGE_CONNECT_CHANNEL:
-                HealthChannel chan = (HealthChannel)msg.obj;
-                String deviceObjectPath =
-                    mBluetoothService.getObjectPathFromAddress(chan.mDevice.getAddress());
-                String configPath = mHealthAppConfigs.get(chan.mConfig);
-                String channelType = getStringChannelType(chan.mChannelType);
-
-                if (!mBluetoothService.createChannelNative(deviceObjectPath, configPath,
-                          channelType, chan.mId)) {
-                    int prevState = chan.mState;
-                    int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-                    callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null,
-                            chan.mId);
-                    mHealthChannels.remove(chan);
-                }
-            }
-        }
-    };
-
-    private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
-        mBluetoothService = service;
-        mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
-        mHealthChannels = new ArrayList<HealthChannel>();
-        mHealthDevices = new HashMap<BluetoothDevice, Integer>();
-        mCallbacks = new HashMap<BluetoothHealthAppConfiguration, IBluetoothHealthCallback>();
-    }
-
-    static synchronized BluetoothHealthProfileHandler getInstance(Context context,
-            BluetoothService service) {
-        if (sInstance == null) sInstance = new BluetoothHealthProfileHandler(context, service);
-        return sInstance;
-    }
-
-    boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
-                                     IBluetoothHealthCallback callback) {
-        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION);
-        msg.obj = config;
-        mHandler.sendMessage(msg);
-        mCallbacks.put(config, callback);
-        return true;
-    }
-
-    boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
-        String path = mHealthAppConfigs.get(config);
-        if (path == null) return false;
-
-        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_APPLICATION);
-        msg.obj = config;
-        mHandler.sendMessage(msg);
-        return true;
-    }
-
-    boolean connectChannelToSource(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        return connectChannel(device, config, BluetoothHealth.CHANNEL_TYPE_ANY);
-    }
-
-    private HealthChannel getMainChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        for (HealthChannel chan: mHealthChannels) {
-            if (chan.mDevice.equals(device) && chan.mConfig.equals(config)) {
-                if (chan.mMainChannel) return chan;
-            }
-        }
-        return null;
-    }
-
-    boolean connectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int channelType) {
-        String deviceObjectPath =
-            mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (deviceObjectPath == null) return false;
-
-        String configPath = mHealthAppConfigs.get(config);
-        if (configPath == null) return false;
-
-        HealthChannel chan = new HealthChannel(device, config, null, false, null);
-        chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTING;
-        chan.mChannelType = channelType;
-        mHealthChannels.add(chan);
-
-        int prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-        int state = BluetoothHealth.STATE_CHANNEL_CONNECTING;
-        callHealthChannelCallback(config, device, prevState, state, null, chan.mId);
-
-        Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_CHANNEL);
-        msg.obj = chan;
-        mHandler.sendMessage(msg);
-
-        return true;
-    }
-
-    private String getStringChannelType(int type) {
-        if (type == BluetoothHealth.CHANNEL_TYPE_RELIABLE) {
-            return "Reliable";
-        } else if (type == BluetoothHealth.CHANNEL_TYPE_STREAMING) {
-            return "Streaming";
-        } else {
-            return "Any";
-        }
-    }
-
-    private String getStringRole(int role) {
-        if (role == BluetoothHealth.SINK_ROLE) {
-            return "Sink";
-        } else if (role == BluetoothHealth.SOURCE_ROLE) {
-            return "Streaming";
-        } else {
-            return null;
-        }
-    }
-
-    private int getChannelId() {
-        // The function doesn't need to be synchronized, as the health profile handler
-        // will only allow one health channel object creation at a time.
-        // In the worst case the while loop will have to break out at some point of
-        // time, because only a limited number of L2CAP channels are possible.
-        int id;
-        boolean found;
-        do {
-            id = sChannelId.incrementAndGet();
-            found = false;
-            for (HealthChannel chan: mHealthChannels) {
-                if (chan.mId == id) found = true;
-            }
-        } while (found);
-        return id;
-    }
-
-    boolean disconnectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int id) {
-        HealthChannel chan = findChannelById(id);
-        if (chan == null) {
-          return false;
-        }
-
-        String deviceObjectPath =
-                mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-        mBluetoothService.releaseChannelFdNative(chan.mChannelPath);
-
-        int prevState = chan.mState;
-        chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
-        callHealthChannelCallback(config, device, prevState, chan.mState,
-                null, chan.mId);
-
-        if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath,
-                                                    chan.mId)) {
-            prevState = chan.mState;
-            chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED;
-            callHealthChannelCallback(config, device, prevState, chan.mState,
-                    chan.mChannelFd, chan.mId);
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    private HealthChannel findChannelById(int id) {
-        for (HealthChannel chan : mHealthChannels) {
-            if (chan.mId == id) return chan;
-        }
-        return null;
-    }
-
-    private HealthChannel findChannelByPath(BluetoothDevice device, String path) {
-        for (HealthChannel chan : mHealthChannels) {
-            if (path.equals(chan.mChannelPath) && device.equals(chan.mDevice)) return chan;
-        }
-        return null;
-    }
-
-    private List<HealthChannel> findChannelByStates(BluetoothDevice device, int[] states) {
-        List<HealthChannel> channels = new ArrayList<HealthChannel>();
-        for (HealthChannel chan: mHealthChannels) {
-            if (chan.mDevice.equals(device)) {
-                for (int state : states) {
-                    if (chan.mState == state) {
-                        channels.add(chan);
-                    }
-                }
-            }
-        }
-        return channels;
-    }
-
-    private HealthChannel findConnectingChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        for (HealthChannel chan : mHealthChannels) {
-            if (chan.mDevice.equals(device) && chan.mConfig.equals(config) &&
-                chan.mState == BluetoothHealth.STATE_CHANNEL_CONNECTING) return chan;
-        }
-        return null;
-    }
-
-    ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        HealthChannel chan = getMainChannel(device, config);
-        if (chan != null) {
-            ParcelFileDescriptor pfd =  null;
-            try {
-                pfd = chan.mChannelFd.dup();
-                return pfd;
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        String objectPath =
-                mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null) return null;
-
-        String mainChannelPath = mBluetoothService.getMainChannelNative(objectPath);
-        if (mainChannelPath == null) return null;
-
-        // We had no record of the main channel but querying Bluez we got a
-        // main channel. We might not have received the PropertyChanged yet for
-        // the main channel creation so update our data structure here.
-        chan = findChannelByPath(device, mainChannelPath);
-        if (chan == null) {
-            errorLog("Main Channel present but we don't have any account of it:" +
-                    device +":" + config);
-            return null;
-        }
-        chan.mMainChannel = true;
-        try {
-            return chan.mChannelFd.dup();
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /*package*/ void onHealthDevicePropertyChanged(String devicePath,
-            String channelPath) {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        String address = mBluetoothService.getAddressFromObjectPath(devicePath);
-        if (address == null) return;
-
-        //TODO: Fix this in Bluez
-        if (channelPath.equals("/")) {
-            // This means that the main channel is being destroyed.
-            return;
-        }
-
-        BluetoothDevice device = adapter.getRemoteDevice(address);
-        BluetoothHealthAppConfiguration config = findHealthApplication(device,
-                channelPath);
-        if (config != null) {
-            HealthChannel chan = findChannelByPath(device, channelPath);
-            if (chan == null) {
-                errorLog("Health Channel is not present:" + channelPath);
-            } else {
-                chan.mMainChannel = true;
-            }
-        }
-    }
-
-    /*package*/ void onHealthDeviceChannelConnectionError(int chanCode,
-                                                          int state) {
-        HealthChannel channel = findChannelById(chanCode);
-        if (channel == null) errorLog("No record of this channel:" + chanCode);
-
-        callHealthChannelCallback(channel.mConfig, channel.mDevice, channel.mState, state, null,
-                chanCode);
-    }
-
-    private BluetoothHealthAppConfiguration findHealthApplication(
-            BluetoothDevice device, String channelPath) {
-        BluetoothHealthAppConfiguration config = null;
-        HealthChannel chan = findChannelByPath(device, channelPath);
-
-        if (chan != null) {
-            config = chan.mConfig;
-        } else {
-            String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
-            if (configPath == null) {
-                errorLog("Config path is null for application");
-            } else {
-                for (Entry<BluetoothHealthAppConfiguration, String> e :
-                        mHealthAppConfigs.entrySet()) {
-                    if (e.getValue().equals(configPath)) {
-                        config = e.getKey();
-                    }
-                }
-                if (config == null) errorLog("No associated application for path:" + configPath);
-            }
-        }
-        return config;
-    }
-
-    /*package*/ void onHealthDeviceChannelChanged(String devicePath,
-            String channelPath, boolean exists) {
-        debugLog("onHealthDeviceChannelChanged: devicePath: " + devicePath +
-                "ChannelPath: " + channelPath + "Exists: " + exists);
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        String address = mBluetoothService.getAddressFromObjectPath(devicePath);
-        if (address == null) return;
-
-        BluetoothDevice device = adapter.getRemoteDevice(address);
-        BluetoothHealthAppConfiguration config;
-        int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-        ParcelFileDescriptor fd;
-        HealthChannel channel;
-        config = findHealthApplication(device, channelPath);
-
-        if (exists) {
-            channel = findConnectingChannel(device, config);
-            if (channel == null) {
-               channel = new HealthChannel(device, config, null, false,
-                       channelPath);
-               channel.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-               mHealthChannels.add(channel);
-            }
-            channel.mChannelPath = channelPath;
-
-            fd = mBluetoothService.getChannelFdNative(channelPath);
-            if (fd == null) {
-                errorLog("Error obtaining fd for channel:" + channelPath);
-                disconnectChannel(device, config, channel.mId);
-                return;
-            }
-            boolean mainChannel =
-                    getMainChannel(device, config) == null ? false : true;
-            if (!mainChannel) {
-                String mainChannelPath =
-                        mBluetoothService.getMainChannelNative(devicePath);
-                if (mainChannelPath == null) {
-                    errorLog("Main Channel Path is null for devicePath:" + devicePath);
-                    return;
-                }
-                if (mainChannelPath.equals(channelPath)) mainChannel = true;
-            }
-
-            channel.mChannelFd = fd;
-            channel.mMainChannel = mainChannel;
-            prevState = channel.mState;
-            state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
-        } else {
-            channel = findChannelByPath(device, channelPath);
-            if (channel == null) {
-                errorLog("Channel not found:" + config + ":" + channelPath);
-                return;
-            }
-            mHealthChannels.remove(channel);
-
-            channel.mChannelFd = null;
-            prevState = channel.mState;
-            state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-        }
-        channel.mState = state;
-        callHealthChannelCallback(config, device, prevState, state, channel.mChannelFd,
-                channel.mId);
-    }
-
-    private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
-            BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd, int id) {
-        broadcastHealthDeviceStateChange(device, prevState, state);
-
-        debugLog("Health Device Callback: " + device + " State Change: "
-                + prevState + "->" + state);
-
-        ParcelFileDescriptor dupedFd = null;
-        if (fd != null) {
-            try {
-                dupedFd = fd.dup();
-            } catch (IOException e) {
-                dupedFd = null;
-                errorLog("Exception while duping: " + e);
-            }
-        }
-
-        IBluetoothHealthCallback callback = mCallbacks.get(config);
-        if (callback != null) {
-            try {
-                callback.onHealthChannelStateChange(config, device, prevState, state, dupedFd, id);
-            } catch (RemoteException e) {
-                errorLog("Remote Exception:" + e);
-            }
-        }
-    }
-
-    private void callHealthApplicationStatusCallback(
-            BluetoothHealthAppConfiguration config, int status) {
-        debugLog("Health Device Application: " + config + " State Change: status:"
-                + status);
-        IBluetoothHealthCallback callback = mCallbacks.get(config);
-        if (callback != null) {
-            try {
-                callback.onHealthAppConfigurationStatusChange(config, status);
-            } catch (RemoteException e) {
-                errorLog("Remote Exception:" + e);
-            }
-        }
-    }
-
-    int getHealthDeviceConnectionState(BluetoothDevice device) {
-        if (mHealthDevices.get(device) == null) {
-            return BluetoothHealth.STATE_DISCONNECTED;
-        }
-        return mHealthDevices.get(device);
-    }
-
-    List<BluetoothDevice> getConnectedHealthDevices() {
-        List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(
-                    new int[] {BluetoothHealth.STATE_CONNECTED});
-        return devices;
-    }
-
-    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(int[] states) {
-        List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(states);
-        return devices;
-    }
-
-    List<BluetoothDevice> lookupHealthDevicesMatchingStates(int[] states) {
-        List<BluetoothDevice> healthDevices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mHealthDevices.keySet()) {
-            int healthDeviceState = getHealthDeviceConnectionState(device);
-            for (int state : states) {
-                if (state == healthDeviceState) {
-                    healthDevices.add(device);
-                    break;
-                }
-            }
-        }
-        return healthDevices;
-    }
-
-    /**
-     * This function sends the intent for the updates on the connection status to the remote device.
-     * Note that multiple channels can be connected to the remote device by multiple applications.
-     * This sends an intent for the update to the device connection status and not the channel
-     * connection status. Only the following state transitions are possible:
-     *
-     * {@link BluetoothHealth#STATE_DISCONNECTED} to {@link BluetoothHealth#STATE_CONNECTING}
-     * {@link BluetoothHealth#STATE_CONNECTING} to {@link BluetoothHealth#STATE_CONNECTED}
-     * {@link BluetoothHealth#STATE_CONNECTED} to {@link BluetoothHealth#STATE_DISCONNECTING}
-     * {@link BluetoothHealth#STATE_DISCONNECTING} to {@link BluetoothHealth#STATE_DISCONNECTED}
-     * {@link BluetoothHealth#STATE_DISCONNECTED} to {@link BluetoothHealth#STATE_CONNECTED}
-     * {@link BluetoothHealth#STATE_CONNECTED} to {@link BluetoothHealth#STATE_DISCONNECTED}
-     * {@link BluetoothHealth#STATE_CONNECTING} to {{@link BluetoothHealth#STATE_DISCONNECTED}
-     *
-     * @param device
-     * @param prevChannelState
-     * @param newChannelState
-     * @hide
-     */
-    private void broadcastHealthDeviceStateChange(BluetoothDevice device, int prevChannelState,
-            int newChannelState) {
-        if (mHealthDevices.get(device) == null) {
-            mHealthDevices.put(device, BluetoothHealth.STATE_DISCONNECTED);
-        }
-
-        int currDeviceState = mHealthDevices.get(device);
-        int newDeviceState = convertState(newChannelState);
-
-        if (currDeviceState != newDeviceState) {
-            List<HealthChannel> chan;
-            switch (currDeviceState) {
-                case BluetoothHealth.STATE_DISCONNECTED:
-                    updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    break;
-                case BluetoothHealth.STATE_CONNECTING:
-                    // Channel got connected.
-                    if (newDeviceState == BluetoothHealth.STATE_CONNECTED) {
-                        updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    } else {
-                        // Channel got disconnected
-                        chan = findChannelByStates(device, new int [] {
-                                    BluetoothHealth.STATE_CHANNEL_CONNECTING,
-                                    BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
-                        if (chan.isEmpty()) {
-                            updateAndSendIntent(device, currDeviceState, newDeviceState);
-                        }
-                    }
-                    break;
-                case BluetoothHealth.STATE_CONNECTED:
-                    // Channel got disconnected or is in disconnecting state.
-                    chan = findChannelByStates(device, new int [] {
-                                BluetoothHealth.STATE_CHANNEL_CONNECTING,
-                                BluetoothHealth.STATE_CHANNEL_CONNECTED});
-                    if (chan.isEmpty()) {
-                        updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    }
-                    break;
-                case BluetoothHealth.STATE_DISCONNECTING:
-                    // Channel got disconnected.
-                    chan = findChannelByStates(device, new int [] {
-                                BluetoothHealth.STATE_CHANNEL_CONNECTING,
-                                BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
-                    if (chan.isEmpty()) {
-                        updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    }
-                    break;
-            }
-        }
-    }
-
-    private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState,
-            int newDeviceState) {
-        mHealthDevices.put(device, newDeviceState);
-        mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.HEALTH,
-                                                    newDeviceState, prevDeviceState);
-    }
-
-    /**
-     * This function converts the channel connection state to device connection state.
-     *
-     * @param state
-     * @return
-     */
-    private int convertState(int state) {
-        switch (state) {
-            case BluetoothHealth.STATE_CHANNEL_CONNECTED:
-                return BluetoothHealth.STATE_CONNECTED;
-            case BluetoothHealth.STATE_CHANNEL_CONNECTING:
-                return BluetoothHealth.STATE_CONNECTING;
-            case BluetoothHealth.STATE_CHANNEL_DISCONNECTING:
-                return BluetoothHealth.STATE_DISCONNECTING;
-            case BluetoothHealth.STATE_CHANNEL_DISCONNECTED:
-                return BluetoothHealth.STATE_DISCONNECTED;
-        }
-        errorLog("Mismatch in Channel and Health Device State");
-        return -1;
-    }
-
-    private static void debugLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
-    private static void errorLog(String msg) {
-        Log.e(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java
deleted file mode 100644
index 31764b0..0000000
--- a/core/java/android/server/BluetoothInputProfileHandler.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothDeviceProfileState;
-import android.bluetooth.BluetoothInputDevice;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfileState;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Message;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This handles all the operations on the HID profile.
- * All functions are called by BluetoothService, as Bluetooth Service
- * is the Service handler for the HID profile.
- */
-final class BluetoothInputProfileHandler {
-    private static final String TAG = "BluetoothInputProfileHandler";
-    private static final boolean DBG = true;
-
-    public static BluetoothInputProfileHandler sInstance;
-    private Context mContext;
-    private BluetoothService mBluetoothService;
-    private final HashMap<BluetoothDevice, Integer> mInputDevices;
-    private final BluetoothProfileState mHidProfileState;
-
-    private BluetoothInputProfileHandler(Context context, BluetoothService service) {
-        mContext = context;
-        mBluetoothService = service;
-        mInputDevices = new HashMap<BluetoothDevice, Integer>();
-        mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID);
-        mHidProfileState.start();
-    }
-
-    static synchronized BluetoothInputProfileHandler getInstance(Context context,
-            BluetoothService service) {
-        if (sInstance == null) sInstance = new BluetoothInputProfileHandler(context, service);
-        return sInstance;
-    }
-
-    boolean connectInputDevice(BluetoothDevice device,
-                                            BluetoothDeviceProfileState state) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null ||
-            getInputDeviceConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
-            getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
-            return false;
-        }
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HID_OUTGOING;
-            msg.obj = state;
-            mHidProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    boolean connectInputDeviceInternal(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING);
-        if (!mBluetoothService.connectInputDeviceNative(objectPath)) {
-            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED);
-            return false;
-        }
-        return true;
-    }
-
-    boolean disconnectInputDevice(BluetoothDevice device,
-                                               BluetoothDeviceProfileState state) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null ||
-                getInputDeviceConnectionState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
-            return false;
-        }
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HID_OUTGOING;
-            msg.obj = state;
-            mHidProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    boolean disconnectInputDeviceInternal(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING);
-        if (!mBluetoothService.disconnectInputDeviceNative(objectPath)) {
-            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTED);
-            return false;
-        }
-        return true;
-    }
-
-    int getInputDeviceConnectionState(BluetoothDevice device) {
-        if (mInputDevices.get(device) == null) {
-            return BluetoothInputDevice.STATE_DISCONNECTED;
-        }
-        return mInputDevices.get(device);
-    }
-
-    List<BluetoothDevice> getConnectedInputDevices() {
-        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
-            new int[] {BluetoothInputDevice.STATE_CONNECTED});
-        return devices;
-    }
-
-    List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) {
-        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(states);
-        return devices;
-    }
-
-    int getInputDevicePriority(BluetoothDevice device) {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
-                BluetoothInputDevice.PRIORITY_UNDEFINED);
-    }
-
-    boolean setInputDevicePriority(BluetoothDevice device, int priority) {
-        if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
-            return false;
-        }
-        return Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
-                priority);
-    }
-
-    List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
-        List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mInputDevices.keySet()) {
-            int inputDeviceState = getInputDeviceConnectionState(device);
-            for (int state : states) {
-                if (state == inputDeviceState) {
-                    inputDevices.add(device);
-                    break;
-                }
-            }
-        }
-        return inputDevices;
-    }
-
-    private void handleInputDeviceStateChange(BluetoothDevice device, int state) {
-        int prevState;
-        if (mInputDevices.get(device) == null) {
-            prevState = BluetoothInputDevice.STATE_DISCONNECTED;
-        } else {
-            prevState = mInputDevices.get(device);
-        }
-        if (prevState == state) return;
-
-        mInputDevices.put(device, state);
-
-        if (getInputDevicePriority(device) >
-              BluetoothInputDevice.PRIORITY_OFF &&
-            state == BluetoothInputDevice.STATE_CONNECTING ||
-            state == BluetoothInputDevice.STATE_CONNECTED) {
-            // We have connected or attempting to connect.
-            // Bump priority
-            setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT);
-        }
-
-        Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothInputDevice.EXTRA_STATE, state);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-
-        debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
-        mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.INPUT_DEVICE, state,
-                                                    prevState);
-    }
-
-    void handleInputDevicePropertyChange(String address, boolean connected) {
-        int state = connected ? BluetoothInputDevice.STATE_CONNECTED :
-            BluetoothInputDevice.STATE_DISCONNECTED;
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        BluetoothDevice device = adapter.getRemoteDevice(address);
-        handleInputDeviceStateChange(device, state);
-    }
-
-    void setInitialInputDevicePriority(BluetoothDevice device, int state) {
-        switch (state) {
-            case BluetoothDevice.BOND_BONDED:
-                if (getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_UNDEFINED) {
-                    setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON);
-                }
-                break;
-            case BluetoothDevice.BOND_NONE:
-                setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_UNDEFINED);
-                break;
-        }
-    }
-
-    private static void debugLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
-    private static void errorLog(String msg) {
-        Log.e(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothPanProfileHandler.java b/core/java/android/server/BluetoothPanProfileHandler.java
deleted file mode 100644
index 41bb87f..0000000
--- a/core/java/android/server/BluetoothPanProfileHandler.java
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothTetheringDataTracker;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources.NotFoundException;
-import android.net.ConnectivityManager;
-import android.net.InterfaceConfiguration;
-import android.net.LinkAddress;
-import android.net.NetworkUtils;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This handles the PAN profile. All calls into this are made
- * from Bluetooth Service.
- */
-final class BluetoothPanProfileHandler {
-    private static final String TAG = "BluetoothPanProfileHandler";
-    private static final boolean DBG = true;
-
-    private ArrayList<String> mBluetoothIfaceAddresses;
-    private int mMaxPanDevices;
-
-    private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
-    private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
-    private static final int BLUETOOTH_PREFIX_LENGTH        = 24;
-    public static BluetoothPanProfileHandler sInstance;
-    private final HashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices;
-    private boolean mTetheringOn;
-    private Context mContext;
-    private BluetoothService mBluetoothService;
-
-    static final String NAP_ROLE = "nap";
-    static final String NAP_BRIDGE = "pan1";
-
-    private BluetoothPanProfileHandler(Context context, BluetoothService service) {
-        mContext = context;
-        mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
-        mBluetoothService = service;
-        mTetheringOn = false;
-        mBluetoothIfaceAddresses = new ArrayList<String>();
-        try {
-            mMaxPanDevices = context.getResources().getInteger(
-                            com.android.internal.R.integer.config_max_pan_devices);
-        } catch (NotFoundException e) {
-            mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
-        }
-    }
-
-    static BluetoothPanProfileHandler getInstance(Context context,
-            BluetoothService service) {
-        if (sInstance == null) sInstance = new BluetoothPanProfileHandler(context, service);
-        return sInstance;
-    }
-
-    boolean isTetheringOn() {
-        return mTetheringOn;
-    }
-
-    boolean allowIncomingTethering() {
-        if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
-            return true;
-        return false;
-    }
-
-    private BroadcastReceiver mTetheringReceiver = null;
-
-    void setBluetoothTethering(boolean value) {
-        if (!value) {
-            disconnectPanServerDevices();
-        }
-
-        if (mBluetoothService.getBluetoothState() != BluetoothAdapter.STATE_ON && value) {
-            IntentFilter filter = new IntentFilter();
-            filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
-            mTetheringReceiver = new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
-                            == BluetoothAdapter.STATE_ON) {
-                        mTetheringOn = true;
-                        mContext.unregisterReceiver(mTetheringReceiver);
-                    }
-                }
-            };
-            mContext.registerReceiver(mTetheringReceiver, filter);
-        } else {
-            mTetheringOn = value;
-        }
-    }
-
-    int getPanDeviceConnectionState(BluetoothDevice device) {
-        BluetoothPanDevice panDevice = mPanDevices.get(device);
-        if (panDevice == null) {
-            return BluetoothPan.STATE_DISCONNECTED;
-        }
-        return panDevice.mState;
-    }
-
-    boolean connectPanDevice(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (DBG) Log.d(TAG, "connect PAN(" + objectPath + ")");
-        if (getPanDeviceConnectionState(device) != BluetoothPan.STATE_DISCONNECTED) {
-            errorLog(device + " already connected to PAN");
-        }
-
-        int connectedCount = 0;
-        for (BluetoothDevice panDevice: mPanDevices.keySet()) {
-            if (getPanDeviceConnectionState(panDevice) == BluetoothPan.STATE_CONNECTED) {
-                connectedCount ++;
-            }
-        }
-        if (connectedCount > 8) {
-            debugLog(device + " could not connect to PAN because 8 other devices are"
-                    + "already connected");
-            return false;
-        }
-
-        // Send interface as null as it is not known
-        handlePanDeviceStateChange(device, null, BluetoothPan.STATE_CONNECTING,
-                                           BluetoothPan.LOCAL_PANU_ROLE);
-        if (mBluetoothService.connectPanDeviceNative(objectPath, "nap")) {
-            debugLog("connecting to PAN");
-            return true;
-        } else {
-            handlePanDeviceStateChange(device, null, BluetoothPan.STATE_DISCONNECTED,
-                                                BluetoothPan.LOCAL_PANU_ROLE);
-            errorLog("could not connect to PAN");
-            return false;
-        }
-    }
-
-    private boolean disconnectPanServerDevices() {
-        debugLog("disconnect all PAN devices");
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            BluetoothPanDevice panDevice = mPanDevices.get(device);
-            int state = panDevice.mState;
-            if (state == BluetoothPan.STATE_CONNECTED &&
-                    panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
-                String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-                handlePanDeviceStateChange(device, panDevice.mIface,
-                        BluetoothPan.STATE_DISCONNECTING, panDevice.mLocalRole);
-
-                if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath,
-                        device.getAddress(),
-                        panDevice.mIface)) {
-                    errorLog("could not disconnect Pan Server Device "+device.getAddress());
-
-                    // Restore prev state
-                    handlePanDeviceStateChange(device, panDevice.mIface, state,
-                            panDevice.mLocalRole);
-
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    List<BluetoothDevice> getConnectedPanDevices() {
-        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            if (getPanDeviceConnectionState(device) == BluetoothPan.STATE_CONNECTED) {
-                devices.add(device);
-            }
-        }
-        return devices;
-    }
-
-    List<BluetoothDevice> getPanDevicesMatchingConnectionStates(int[] states) {
-        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            int panDeviceState = getPanDeviceConnectionState(device);
-            for (int state : states) {
-                if (state == panDeviceState) {
-                    devices.add(device);
-                    break;
-                }
-            }
-        }
-        return devices;
-    }
-
-    boolean disconnectPanDevice(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        debugLog("disconnect PAN(" + objectPath + ")");
-
-        int state = getPanDeviceConnectionState(device);
-        if (state != BluetoothPan.STATE_CONNECTED) {
-            debugLog(device + " already disconnected from PAN");
-            return false;
-        }
-
-        BluetoothPanDevice panDevice = mPanDevices.get(device);
-
-        if (panDevice == null) {
-            errorLog("No record for this Pan device:" + device);
-            return false;
-        }
-
-        handlePanDeviceStateChange(device, panDevice.mIface, BluetoothPan.STATE_DISCONNECTING,
-                                    panDevice.mLocalRole);
-        if (panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
-            if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath, device.getAddress(),
-                    panDevice.mIface)) {
-                // Restore prev state, this shouldn't happen
-                handlePanDeviceStateChange(device, panDevice.mIface, state, panDevice.mLocalRole);
-                return false;
-            }
-        } else {
-            if (!mBluetoothService.disconnectPanDeviceNative(objectPath)) {
-                // Restore prev state, this shouldn't happen
-                handlePanDeviceStateChange(device, panDevice.mIface, state, panDevice.mLocalRole);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    void handlePanDeviceStateChange(BluetoothDevice device,
-                                                 String iface, int state, int role) {
-        int prevState;
-        String ifaceAddr = null;
-        BluetoothPanDevice panDevice = mPanDevices.get(device);
-
-        if (panDevice == null) {
-            prevState = BluetoothPan.STATE_DISCONNECTED;
-        } else {
-            prevState = panDevice.mState;
-            ifaceAddr = panDevice.mIfaceAddr;
-        }
-        if (prevState == state) return;
-
-        if (role == BluetoothPan.LOCAL_NAP_ROLE) {
-            if (state == BluetoothPan.STATE_CONNECTED) {
-                ifaceAddr = enableTethering(iface);
-                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
-            } else if (state == BluetoothPan.STATE_DISCONNECTED) {
-                if (ifaceAddr != null) {
-                    mBluetoothIfaceAddresses.remove(ifaceAddr);
-                    ifaceAddr = null;
-                }
-            }
-        } else {
-            // PANU Role = reverse Tether
-            if (state == BluetoothPan.STATE_CONNECTED) {
-                BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
-            } else if (state == BluetoothPan.STATE_DISCONNECTED &&
-                  (prevState == BluetoothPan.STATE_CONNECTED ||
-                  prevState == BluetoothPan.STATE_DISCONNECTING)) {
-                BluetoothTetheringDataTracker.getInstance().stopReverseTether(panDevice.mIface);
-            }
-        }
-
-        if (panDevice == null) {
-            panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, role);
-            mPanDevices.put(device, panDevice);
-        } else {
-            panDevice.mState = state;
-            panDevice.mIfaceAddr = ifaceAddr;
-            panDevice.mLocalRole = role;
-            panDevice.mIface = iface;
-        }
-
-        Intent intent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothPan.EXTRA_STATE, state);
-        intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-
-        debugLog("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
-        mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.PAN, state,
-                                                    prevState);
-    }
-
-    private class BluetoothPanDevice {
-        private int mState;
-        private String mIfaceAddr;
-        private String mIface;
-        private int mLocalRole; // Which local role is this PAN device bound to
-
-        BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
-            mState = state;
-            mIfaceAddr = ifaceAddr;
-            mIface = iface;
-            mLocalRole = localRole;
-        }
-    }
-
-    private String createNewTetheringAddressLocked() {
-        if (getConnectedPanDevices().size() == mMaxPanDevices) {
-            debugLog ("Max PAN device connections reached");
-            return null;
-        }
-        String address = BLUETOOTH_IFACE_ADDR_START;
-        while (true) {
-            if (mBluetoothIfaceAddresses.contains(address)) {
-                String[] addr = address.split("\\.");
-                Integer newIp = Integer.parseInt(addr[2]) + 1;
-                address = address.replace(addr[2], newIp.toString());
-            } else {
-                break;
-            }
-        }
-        mBluetoothIfaceAddresses.add(address);
-        return address;
-    }
-
-    // configured when we start tethering
-    private String enableTethering(String iface) {
-        debugLog("updateTetherState:" + iface);
-
-        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-        ConnectivityManager cm =
-            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
-
-        // bring toggle the interfaces
-        String[] currentIfaces = new String[0];
-        try {
-            currentIfaces = service.listInterfaces();
-        } catch (Exception e) {
-            Log.e(TAG, "Error listing Interfaces :" + e);
-            return null;
-        }
-
-        boolean found = false;
-        for (String currIface: currentIfaces) {
-            if (currIface.equals(iface)) {
-                found = true;
-                break;
-            }
-        }
-
-        if (!found) return null;
-
-        String address = createNewTetheringAddressLocked();
-        if (address == null) return null;
-
-        InterfaceConfiguration ifcg = null;
-        try {
-            ifcg = service.getInterfaceConfig(iface);
-            if (ifcg != null) {
-                final LinkAddress linkAddr = ifcg.getLinkAddress();
-                InetAddress addr = null;
-                if (linkAddr == null || (addr = linkAddr.getAddress()) == null ||
-                        addr.equals(NetworkUtils.numericToInetAddress("0.0.0.0")) ||
-                        addr.equals(NetworkUtils.numericToInetAddress("::0"))) {
-                    addr = NetworkUtils.numericToInetAddress(address);
-                }
-                ifcg.setInterfaceUp();
-                ifcg.clearFlag("running");
-                ifcg.setLinkAddress(new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH));
-                service.setInterfaceConfig(iface, ifcg);
-                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                    Log.e(TAG, "Error tethering "+iface);
-                }
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
-            return null;
-        }
-        return address;
-    }
-
-    private static void debugLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
-    private static void errorLog(String msg) {
-        Log.e(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
deleted file mode 100755
index 6296b11..0000000
--- a/core/java/android/server/BluetoothService.java
+++ /dev/null
@@ -1,2924 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothService.java
- * and make the contructor package private again.
- *
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothDeviceProfileState;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.bluetooth.BluetoothInputDevice;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfileState;
-import android.bluetooth.BluetoothSocket;
-import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetooth;
-import android.bluetooth.IBluetoothCallback;
-import android.bluetooth.IBluetoothHealthCallback;
-import android.bluetooth.IBluetoothStateChangeCallback;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.app.IBatteryStats;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.io.RandomAccessFile;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-public class BluetoothService extends IBluetooth.Stub {
-    private static final String TAG = "BluetoothService";
-    private static final boolean DBG = true;
-
-    private int mNativeData;
-    private BluetoothEventLoop mEventLoop;
-    private BluetoothHeadset mHeadsetProxy;
-    private BluetoothInputDevice mInputDevice;
-    private BluetoothPan mPan;
-    private boolean mIsAirplaneSensitive;
-    private boolean mIsAirplaneToggleable;
-    private BluetoothAdapterStateMachine mBluetoothState;
-    private int[] mAdapterSdpHandles;
-    private ParcelUuid[] mAdapterUuids;
-
-    private BluetoothAdapter mAdapter;  // constant after init()
-    private final BluetoothBondState mBondState;  // local cache of bondings
-    private final IBatteryStats mBatteryStats;
-    private final Context mContext;
-    private Map<Integer, IBluetoothStateChangeCallback> mStateChangeTracker =
-        Collections.synchronizedMap(new HashMap<Integer, IBluetoothStateChangeCallback>());
-
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
-    private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr";
-    private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin";
-
-    private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address";
-    private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings";
-
-    private static final int MESSAGE_UUID_INTENT = 1;
-    private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
-    private static final int MESSAGE_REMOVE_SERVICE_RECORD = 3;
-
-    private static final int RFCOMM_RECORD_REAPER = 10;
-    private static final int STATE_CHANGE_REAPER = 11;
-
-    // The time (in millisecs) to delay the pairing attempt after the first
-    // auto pairing attempt fails. We use an exponential delay with
-    // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
-    // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
-    private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
-    private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
-
-    // The timeout used to sent the UUIDs Intent
-    // This timeout should be greater than the page timeout
-    private static final int UUID_INTENT_DELAY = 6000;
-
-    /** Always retrieve RFCOMM channel for these SDP UUIDs */
-    private static final ParcelUuid[] RFCOMM_UUIDS = {
-            BluetoothUuid.Handsfree,
-            BluetoothUuid.HSP,
-            BluetoothUuid.ObexObjectPush };
-
-    private final BluetoothAdapterProperties mAdapterProperties;
-    private final BluetoothDeviceProperties mDeviceProperties;
-
-    private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache;
-    private final ArrayList<String> mUuidIntentTracker;
-    private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker;
-
-    private static class ServiceRecordClient {
-        int pid;
-        IBinder binder;
-        IBinder.DeathRecipient death;
-    }
-    private final HashMap<Integer, ServiceRecordClient> mServiceRecordToPid;
-
-    private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
-    private final BluetoothProfileState mA2dpProfileState;
-    private final BluetoothProfileState mHfpProfileState;
-
-    private BluetoothA2dpService mA2dpService;
-    private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData;
-
-    private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0;
-
-    private static String mDockAddress;
-    private String mDockPin;
-
-    private boolean mAllowConnect = true;
-
-    private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
-    private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
-    private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
-    private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler;
-    private static final String INCOMING_CONNECTION_FILE =
-      "/data/misc/bluetooth/incoming_connection.conf";
-    private HashMap<String, Pair<Integer, String>> mIncomingConnections;
-    private HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState;
-
-    private static class RemoteService {
-        public String address;
-        public ParcelUuid uuid;
-        public RemoteService(String address, ParcelUuid uuid) {
-            this.address = address;
-            this.uuid = uuid;
-        }
-        @Override
-        public boolean equals(Object o) {
-            if (o instanceof RemoteService) {
-                RemoteService service = (RemoteService)o;
-                return address.equals(service.address) && uuid.equals(service.uuid);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 1;
-            hash = hash * 31 + (address == null ? 0 : address.hashCode());
-            hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode());
-            return hash;
-        }
-    }
-
-    static {
-        classInitNative();
-    }
-
-    public BluetoothService(Context context) {
-        mContext = context;
-
-        // Need to do this in place of:
-        // mBatteryStats = BatteryStatsService.getService();
-        // Since we can not import BatteryStatsService from here. This class really needs to be
-        // moved to java/services/com/android/server/
-        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
-
-        initializeNativeDataNative();
-
-        if (isEnabledNative() == 1) {
-            Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");
-            disableNative();
-        }
-
-        mBondState = new BluetoothBondState(context, this);
-        mAdapterProperties = new BluetoothAdapterProperties(context, this);
-        mDeviceProperties = new BluetoothDeviceProperties(this);
-
-        mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>();
-        mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();
-        mUuidIntentTracker = new ArrayList<String>();
-        mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
-        mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>();
-        mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
-        mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
-        mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
-
-        mHfpProfileState.start();
-        mA2dpProfileState.start();
-
-        IntentFilter filter = new IntentFilter();
-        registerForAirplaneMode(filter);
-
-        filter.addAction(Intent.ACTION_DOCK_EVENT);
-        mContext.registerReceiver(mReceiver, filter);
-        mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
-        mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
-        mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
-        mIncomingConnections = new HashMap<String, Pair<Integer, String>>();
-        mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>();
-    }
-
-    public static synchronized String readDockBluetoothAddress() {
-        if (mDockAddress != null) return mDockAddress;
-
-        BufferedInputStream file = null;
-        String dockAddress;
-        try {
-            file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH));
-            byte[] address = new byte[17];
-            file.read(address);
-            dockAddress = new String(address);
-            dockAddress = dockAddress.toUpperCase();
-            if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) {
-                mDockAddress = dockAddress;
-                return mDockAddress;
-            } else {
-                Log.e(TAG, "CheckBluetoothAddress failed for car dock address: "
-                        + dockAddress);
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException while trying to read dock address");
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while trying to read dock address");
-        } finally {
-            if (file != null) {
-                try {
-                    file.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        mDockAddress = null;
-        return null;
-    }
-
-    private synchronized boolean writeDockPin() {
-        BufferedWriter out = null;
-        try {
-            out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH));
-
-            // Generate a random 4 digit pin between 0000 and 9999
-            // This is not truly random but good enough for our purposes.
-            int pin = (int) Math.floor(Math.random() * 10000);
-
-            mDockPin = String.format("%04d", pin);
-            out.write(mDockPin);
-            return true;
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin");
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while while trying to write dock pairing pin");
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        mDockPin = null;
-        return false;
-    }
-
-    /*package*/ synchronized String getDockPin() {
-        return mDockPin;
-    }
-
-    public synchronized void initAfterRegistration() {
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
-        mBluetoothState.start();
-        if (mContext.getResources().getBoolean
-            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT);
-        }
-        mEventLoop = mBluetoothState.getBluetoothEventLoop();
-    }
-
-    public synchronized void initAfterA2dpRegistration() {
-        mEventLoop.getProfileProxy();
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        mContext.unregisterReceiver(mReceiver);
-        try {
-            cleanupNativeDataNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    public boolean isEnabled() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return isEnabledInternal();
-    }
-
-    private boolean isEnabledInternal() {
-        return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON);
-    }
-
-    public int getBluetoothState() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return getBluetoothStateInternal();
-    }
-
-    int getBluetoothStateInternal() {
-        return mBluetoothState.getBluetoothAdapterState();
-    }
-
-    /**
-     * Bring down bluetooth and disable BT in settings. Returns true on success.
-     */
-    public boolean disable() {
-        return disable(true);
-    }
-
-    /**
-     * Bring down bluetooth. Returns true on success.
-     *
-     * @param saveSetting If true, persist the new setting
-     */
-    public synchronized boolean disable(boolean saveSetting) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
-
-        int adapterState = getBluetoothStateInternal();
-
-        switch (adapterState) {
-        case BluetoothAdapter.STATE_OFF:
-            return true;
-        case BluetoothAdapter.STATE_ON:
-            break;
-        default:
-            return false;
-        }
-
-        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting);
-        return true;
-    }
-
-    synchronized void disconnectDevices() {
-        // Disconnect devices handled by BluetoothService.
-        for (BluetoothDevice device: getConnectedInputDevices()) {
-            disconnectInputDevice(device);
-        }
-
-        for (BluetoothDevice device: getConnectedPanDevices()) {
-            disconnectPanDevice(device);
-        }
-    }
-
-    /**
-     * The Bluetooth has been turned off, but hot. Do bonding, profile cleanup
-     */
-    synchronized void finishDisable() {
-        // mark in progress bondings as cancelled
-        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
-            mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
-                                    BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
-        }
-
-        // Stop the profile state machine for bonded devices.
-        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) {
-            removeProfileState(address);
-        }
-
-        // update mode
-        Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-        intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
-    /**
-     * Local clean up after broadcasting STATE_OFF intent
-     */
-    synchronized void cleanupAfterFinishDisable() {
-        mAdapterProperties.clear();
-
-        for (Integer srHandle : mServiceRecordToPid.keySet()) {
-            removeServiceRecordNative(srHandle);
-        }
-        mServiceRecordToPid.clear();
-
-        mProfilesConnected = 0;
-        mProfilesConnecting = 0;
-        mProfilesDisconnecting = 0;
-        mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
-        mAdapterUuids = null;
-        mAdapterSdpHandles = null;
-
-        // Log bluetooth off to battery stats.
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteBluetoothOff();
-        } catch (RemoteException e) {
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    /**
-     * power off Bluetooth
-     */
-    synchronized void shutoffBluetooth() {
-        if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
-        setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
-                BluetoothPanProfileHandler.NAP_BRIDGE);
-        tearDownNativeDataNative();
-    }
-
-    /**
-     * Data clean up after Bluetooth shutoff
-     */
-    synchronized void cleanNativeAfterShutoffBluetooth() {
-        // Ths method is called after shutdown of event loop in the Bluetooth shut down
-        // procedure
-
-        // the adapter property could be changed before event loop is stoped, clear it again
-        mAdapterProperties.clear();
-        disableNative();
-    }
-
-    /** Bring up BT and persist BT on in settings */
-    public boolean enable() {
-        return enable(true, true);
-    }
-
-    /**
-     * Enable this Bluetooth device, asynchronously.
-     * This turns on/off the underlying hardware.
-     *
-     * @param saveSetting If true, persist the new state of BT in settings
-     * @param allowConnect If true, auto-connects device when BT is turned on
-     *                     and allows incoming A2DP/HSP connections
-     * @return True on success (so far)
-     */
-    public synchronized boolean enable(boolean saveSetting, boolean allowConnect) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-
-        // Airplane mode can prevent Bluetooth radio from being turned on.
-        if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
-            return false;
-        }
-        mAllowConnect = allowConnect;
-        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
-        return true;
-    }
-
-    /**
-     * Enable this Bluetooth device, asynchronously, but does not
-     * auto-connect devices. In this state the Bluetooth adapter
-     * also does not allow incoming A2DP/HSP connections (that
-     * must go through this service), but does allow communication
-     * on RFCOMM sockets implemented outside of this service (ie BTOPP).
-     * This method is used to temporarily enable Bluetooth
-     * for data transfer, without changing
-     *
-     * This turns on/off the underlying hardware.
-     *
-     * @return True on success (so far)
-     */
-    public boolean enableNoAutoConnect() {
-        return enable(false, false);
-    }
-
-    /**
-     * Turn on Bluetooth Module, Load firmware, and do all the preparation
-     * needed to get the Bluetooth Module ready but keep it not discoverable
-     * and not connectable.
-     */
-    /* package */ synchronized boolean prepareBluetooth() {
-        if (!setupNativeDataNative()) {
-            return false;
-        }
-        switchConnectable(false);
-
-        // Bluetooth stack needs a small delay here before adding
-        // SDP records, otherwise dbus stalls for over 30 seconds 1 out of 50 runs
-        try {
-            Thread.sleep(50);
-        } catch (InterruptedException e) {}
-        updateSdpRecords();
-        return true;
-    }
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MESSAGE_UUID_INTENT:
-                String address = (String)msg.obj;
-                if (address != null) {
-                    sendUuidIntent(address);
-                    makeServiceChannelCallbacks(address);
-                }
-                break;
-            case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
-                address = (String)msg.obj;
-                if (address == null) return;
-                int attempt = mBondState.getAttempt(address);
-
-                // Try only if attemps are in progress and cap it 2 attempts
-                // The 2 attempts cap is a fail safe if the stack returns
-                // an incorrect error code for bonding failures and if the pin
-                // is entered wrongly twice we should abort.
-                if (attempt > 0 && attempt <= 2) {
-                    mBondState.attempt(address);
-                    createBond(address);
-                    return;
-                }
-                if (attempt > 0) mBondState.clearPinAttempts(address);
-                break;
-            case MESSAGE_REMOVE_SERVICE_RECORD:
-                Pair<Integer, Integer> pair = (Pair<Integer, Integer>) msg.obj;
-                checkAndRemoveRecord(pair.first, pair.second);
-                break;
-            }
-        }
-    };
-
-    private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) {
-        //Register SDP records.
-        int[] svcIdentifiers = new int[uuids.size()];
-        for (int i = 0; i < uuids.size(); i++) {
-            svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i));
-        }
-        mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers);
-    }
-
-    private synchronized void updateSdpRecords() {
-        ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
-
-        Resources R = mContext.getResources();
-
-        // Add the default records
-        if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
-            uuids.add(BluetoothUuid.HSP_AG);
-            uuids.add(BluetoothUuid.ObexObjectPush);
-        }
-
-        if (R.getBoolean(com.android.internal.R.bool.config_voice_capable)) {
-            uuids.add(BluetoothUuid.Handsfree_AG);
-            uuids.add(BluetoothUuid.PBAP_PSE);
-        }
-
-        // Add SDP records for profiles maintained by Android userspace
-        addReservedSdpRecords(uuids);
-
-        // Bluetooth stack need some a small delay here before adding more
-        // SDP records, otherwise dbus stalls for over 30 seconds 1 out of 50 runs
-        try {
-            Thread.sleep(50);
-        } catch (InterruptedException e) {}
-
-        if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
-            // Enable profiles maintained by Bluez userspace.
-            setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
-                   BluetoothPanProfileHandler.NAP_BRIDGE);
-
-            // Add SDP records for profiles maintained by Bluez userspace
-            uuids.add(BluetoothUuid.AudioSource);
-            uuids.add(BluetoothUuid.AvrcpTarget);
-            uuids.add(BluetoothUuid.NAP);
-        }
-
-        // Cannot cast uuids.toArray directly since ParcelUuid is parcelable
-        mAdapterUuids = new ParcelUuid[uuids.size()];
-        for (int i = 0; i < uuids.size(); i++) {
-            mAdapterUuids[i] = uuids.get(i);
-        }
-    }
-
-    /**
-     * This function is called from Bluetooth Event Loop when onPropertyChanged
-     * for adapter comes in with UUID property.
-     * @param uuidsThe uuids of adapter as reported by Bluez.
-     */
-    /*package*/ synchronized void updateBluetoothState(String uuids) {
-        ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
-
-        if (mAdapterUuids != null &&
-            BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
-            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);
-        }
-    }
-
-    /**
-     * This method is called immediately before Bluetooth module is turned on after
-     * the adapter became pariable.
-     * It inits bond state and profile state before STATE_ON intent is broadcasted.
-     */
-    /*package*/ void initBluetoothAfterTurningOn() {
-        String discoverable = getProperty("Discoverable", false);
-        String timeout = getProperty("DiscoverableTimeout", false);
-        if (timeout == null) {
-            Log.w(TAG, "Null DiscoverableTimeout property");
-            // assign a number, anything not 0
-            timeout = "1";
-        }
-        if (discoverable.equals("true") && Integer.valueOf(timeout) != 0) {
-            setAdapterPropertyBooleanNative("Discoverable", 0);
-        }
-        mBondState.initBondState();
-        initProfileState();
-        getProfileProxy();
-    }
-
-    /**
-     * This method is called immediately after Bluetooth module is turned on.
-     * It starts auto-connection and places bluetooth on sign onto the battery
-     * stats
-     */
-    /*package*/ void runBluetooth() {
-        autoConnect();
-
-        // Log bluetooth on to battery stats.
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteBluetoothOn();
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    /*package*/ synchronized boolean attemptAutoPair(String address) {
-        if (!mBondState.hasAutoPairingFailed(address) &&
-                !mBondState.isAutoPairingBlacklisted(address)) {
-            mBondState.attempt(address);
-            setPin(address, BluetoothDevice.convertPinToBytes("0000"));
-            return true;
-        }
-        return false;
-    }
-
-    /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) {
-        // Check for keyboards which have fixed PIN 0000 as the pairing pin
-        return mBondState.isFixedPinZerosAutoPairKeyboard(address);
-    }
-
-    /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) {
-        if (result == BluetoothDevice.BOND_SUCCESS) {
-            setBondState(address, BluetoothDevice.BOND_BONDED);
-            if (mBondState.isAutoPairingAttemptsInProgress(address)) {
-                mBondState.clearPinAttempts(address);
-            }
-        } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
-                mBondState.getAttempt(address) == 1) {
-            mBondState.addAutoPairingFailure(address);
-            pairingAttempt(address, result);
-        } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
-              mBondState.isAutoPairingAttemptsInProgress(address)) {
-            pairingAttempt(address, result);
-        } else {
-            setBondState(address, BluetoothDevice.BOND_NONE, result);
-            if (mBondState.isAutoPairingAttemptsInProgress(address)) {
-                mBondState.clearPinAttempts(address);
-            }
-        }
-    }
-
-    /*package*/ synchronized String getPendingOutgoingBonding() {
-        return mBondState.getPendingOutgoingBonding();
-    }
-
-    private void pairingAttempt(String address, int result) {
-        // This happens when our initial guess of "0000" as the pass key
-        // fails. Try to create the bond again and display the pin dialog
-        // to the user. Use back-off while posting the delayed
-        // message. The initial value is
-        // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
-        // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
-        // reached, display an error to the user.
-        int attempt = mBondState.getAttempt(address);
-        if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
-                    MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
-            mBondState.clearPinAttempts(address);
-            setBondState(address, BluetoothDevice.BOND_NONE, result);
-            return;
-        }
-
-        Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
-        message.obj = address;
-        boolean postResult =  mHandler.sendMessageDelayed(message,
-                                        attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
-        if (!postResult) {
-            mBondState.clearPinAttempts(address);
-            setBondState(address,
-                    BluetoothDevice.BOND_NONE, result);
-            return;
-        }
-    }
-
-    /*package*/ BluetoothDevice getRemoteDevice(String address) {
-        return mAdapter.getRemoteDevice(address);
-    }
-
-    private static String toBondStateString(int bondState) {
-        switch (bondState) {
-        case BluetoothDevice.BOND_NONE:
-            return "not bonded";
-        case BluetoothDevice.BOND_BONDING:
-            return "bonding";
-        case BluetoothDevice.BOND_BONDED:
-            return "bonded";
-        default:
-            return "??????";
-        }
-    }
-
-    public synchronized boolean setName(String name) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (name == null) {
-            return false;
-        }
-        return setPropertyString("Name", name);
-    }
-
-    //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean
-    // Either have a single property function with Object as the parameter
-    // or have a function for each property and then obfuscate in the JNI layer.
-    // The following looks dirty.
-    private boolean setPropertyString(String key, String value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-        return setAdapterPropertyStringNative(key, value);
-    }
-
-    private boolean setPropertyInteger(String key, int value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-        return setAdapterPropertyIntegerNative(key, value);
-    }
-
-    private boolean setPropertyBoolean(String key, boolean value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-        return setAdapterPropertyBooleanNative(key, value ? 1 : 0);
-    }
-
-    /**
-     * Set the discoverability window for the device.  A timeout of zero
-     * makes the device permanently discoverable (if the device is
-     * discoverable).  Setting the timeout to a nonzero value does not make
-     * a device discoverable; you need to call setMode() to make the device
-     * explicitly discoverable.
-     *
-     * @param timeout The discoverable timeout in seconds.
-     */
-    public synchronized boolean setDiscoverableTimeout(int timeout) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        return setPropertyInteger("DiscoverableTimeout", timeout);
-    }
-
-    public synchronized boolean setScanMode(int mode, int duration) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
-                                                "Need WRITE_SECURE_SETTINGS permission");
-        boolean pairable;
-        boolean discoverable;
-
-        switch (mode) {
-        case BluetoothAdapter.SCAN_MODE_NONE:
-            pairable = false;
-            discoverable = false;
-            break;
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-            pairable = true;
-            discoverable = false;
-            break;
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-            pairable = true;
-            discoverable = true;
-            if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds");
-            break;
-        default:
-            Log.w(TAG, "Requested invalid scan mode " + mode);
-            return false;
-        }
-
-        setPropertyBoolean("Discoverable", discoverable);
-        setPropertyBoolean("Pairable", pairable);
-        return true;
-    }
-
-    /**
-     * @param on true set the local Bluetooth module to be connectable
-     *                The dicoverability is recovered to what it was before
-     *                switchConnectable(false) call
-     *           false set the local Bluetooth module to be not connectable
-     *                 and not dicoverable
-     */
-    /*package*/ synchronized void switchConnectable(boolean on) {
-        setAdapterPropertyBooleanNative("Powered", on ? 1 : 0);
-    }
-
-    /*package*/ synchronized void setPairable() {
-        String pairableString = getProperty("Pairable", false);
-        if (pairableString == null) {
-            Log.e(TAG, "null pairableString");
-            return;
-        }
-        if (pairableString.equals("false")) {
-            setAdapterPropertyBooleanNative("Pairable", 1);
-        }
-    }
-
-    /*package*/ String getProperty(String name, boolean checkState) {
-        // If checkState is false, check if the event loop is running.
-        // before making the call to Bluez
-        if (checkState) {
-            if (!isEnabledInternal()) return null;
-        } else if (!mEventLoop.isEventLoopRunning()) {
-            return null;
-        }
-
-        return mAdapterProperties.getProperty(name);
-    }
-
-    BluetoothAdapterProperties getAdapterProperties() {
-        return mAdapterProperties;
-    }
-
-    BluetoothDeviceProperties getDeviceProperties() {
-        return mDeviceProperties;
-    }
-
-    boolean isRemoteDeviceInCache(String address) {
-        return mDeviceProperties.isInCache(address);
-    }
-
-    void setRemoteDeviceProperty(String address, String name, String value) {
-        mDeviceProperties.setProperty(address, name, value);
-    }
-
-    void updateRemoteDevicePropertiesCache(String address) {
-        mDeviceProperties.updateCache(address);
-    }
-
-    public synchronized String getAddress() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        // Don't check state since we want to provide address, even if BT is off
-        return getProperty("Address", false);
-    }
-
-    public synchronized String getName() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        // Don't check state since we want to provide name, even if BT is off
-        return getProperty("Name", false);
-    }
-
-    public ParcelUuid[] getUuids() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        String value =  getProperty("UUIDs", true);
-        if (value == null) return null;
-        return convertStringToParcelUuid(value);
-    }
-
-    private ParcelUuid[] convertStringToParcelUuid(String value) {
-        String[] uuidStrings = null;
-        // The UUIDs are stored as a "," separated string.
-        uuidStrings = value.split(",");
-        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
-
-        for (int i = 0; i < uuidStrings.length; i++) {
-            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
-        }
-        return uuids;
-    }
-
-    /**
-     * Returns the user-friendly name of a remote device.  This value is
-     * returned from our local cache, which is updated when onPropertyChange
-     * event is received.
-     * Do not expect to retrieve the updated remote name immediately after
-     * changing the name on the remote device.
-     *
-     * @param address Bluetooth address of remote device.
-     *
-     * @return The user-friendly name of the specified remote device.
-     */
-    public synchronized String getRemoteName(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return null;
-        }
-        return mDeviceProperties.getProperty(address, "Name");
-    }
-
-    /**
-     * Returns alias of a remote device.  This value is returned from our
-     * local cache, which is updated when onPropertyChange event is received.
-     *
-     * @param address Bluetooth address of remote device.
-     *
-     * @return The alias of the specified remote device.
-     */
-    public synchronized String getRemoteAlias(String address) {
-
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return null;
-        }
-        return mDeviceProperties.getProperty(address, "Alias");
-    }
-
-    /**
-     * Set the alias of a remote device.
-     *
-     * @param address Bluetooth address of remote device.
-     * @param alias new alias to change to
-     * @return true on success, false on error
-     */
-    public synchronized boolean setRemoteAlias(String address, String alias) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-
-        return setDevicePropertyStringNative(getObjectPathFromAddress(address),
-                                             "Alias", alias);
-    }
-
-    /**
-     * Get the discoverability window for the device.  A timeout of zero
-     * means that the device is permanently discoverable (if the device is
-     * in the discoverable mode).
-     *
-     * @return The discoverability window of the device, in seconds.  A negative
-     *         value indicates an error.
-     */
-    public int getDiscoverableTimeout() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        String timeout = getProperty("DiscoverableTimeout", true);
-        if (timeout != null)
-           return Integer.valueOf(timeout);
-        else
-            return -1;
-    }
-
-    public int getScanMode() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal())
-            return BluetoothAdapter.SCAN_MODE_NONE;
-
-        boolean pairable = getProperty("Pairable", true).equals("true");
-        boolean discoverable = getProperty("Discoverable", true).equals("true");
-        return bluezStringToScanMode (pairable, discoverable);
-    }
-
-    public synchronized boolean startDiscovery() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        return startDiscoveryNative();
-    }
-
-    public synchronized boolean cancelDiscovery() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        return stopDiscoveryNative();
-    }
-
-    public boolean isDiscovering() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        String discoveringProperty = getProperty("Discovering", false);
-        if (discoveringProperty == null) {
-            return false;
-        }
-
-        return discoveringProperty.equals("true");
-    }
-
-    private boolean isBondingFeasible(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-
-        if (mBondState.getPendingOutgoingBonding() != null) {
-            Log.d(TAG, "Ignoring createBond(): another device is bonding");
-            // a different device is currently bonding, fail
-            return false;
-        }
-
-        // Check for bond state only if we are not performing auto
-        // pairing exponential back-off attempts.
-        if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
-                mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) {
-            Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded");
-            return false;
-        }
-
-        if (address.equals(mDockAddress)) {
-            if (!writeDockPin()) {
-                Log.e(TAG, "Error while writing Pin for the dock");
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public synchronized boolean createBond(String address) {
-        if (!isBondingFeasible(address)) return false;
-
-        if (!createPairedDeviceNative(address, 60000  /*1 minute*/ )) {
-            return false;
-        }
-
-        mBondState.setPendingOutgoingBonding(address);
-        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
-
-        return true;
-    }
-
-    public synchronized boolean createBondOutOfBand(String address, byte[] hash,
-                                                    byte[] randomizer) {
-        if (!isBondingFeasible(address)) return false;
-
-        if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) {
-            return false;
-        }
-
-        setDeviceOutOfBandData(address, hash, randomizer);
-        mBondState.setPendingOutgoingBonding(address);
-        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
-
-        return true;
-    }
-
-    public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash,
-            byte[] randomizer) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer);
-
-        if (DBG) {
-            Log.d(TAG, "Setting out of band data for: " + address + ":" +
-                  Arrays.toString(hash) + ":" + Arrays.toString(randomizer));
-        }
-
-        mDeviceOobData.put(address, value);
-        return true;
-    }
-
-    Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) {
-        return mDeviceOobData.get(device.getAddress());
-    }
-
-
-    public synchronized byte[] readOutOfBandData() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return null;
-
-        return readAdapterOutOfBandDataNative();
-    }
-
-    public synchronized boolean cancelBondProcess(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-        if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
-            return false;
-        }
-
-        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
-                                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
-        cancelDeviceCreationNative(address);
-        return true;
-    }
-
-    public synchronized boolean removeBond(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            state.sendMessage(BluetoothDeviceProfileState.UNPAIR);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public synchronized boolean removeBondInternal(String address) {
-        // Unset the trusted device state and then unpair
-        setTrust(address, false);
-        return removeDeviceNative(getObjectPathFromAddress(address));
-    }
-
-    public synchronized String[] listBonds() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return mBondState.listInState(BluetoothDevice.BOND_BONDED);
-    }
-
-    /*package*/ synchronized String[] listInState(int state) {
-      return mBondState.listInState(state);
-    }
-
-    public synchronized int getBondState(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return BluetoothDevice.ERROR;
-        }
-        return mBondState.getBondState(address.toUpperCase());
-    }
-
-    /*package*/ synchronized boolean setBondState(String address, int state) {
-        return setBondState(address, state, 0);
-    }
-
-    /*package*/ synchronized boolean setBondState(String address, int state, int reason) {
-        mBondState.setBondState(address.toUpperCase(), state, reason);
-        return true;
-    }
-
-    public synchronized boolean isBluetoothDock(String address) {
-        SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
-                Context.MODE_PRIVATE);
-
-        return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address);
-    }
-
-    /*package*/ String[] getRemoteDeviceProperties(String address) {
-        if (!isEnabledInternal()) return null;
-
-        String objectPath = getObjectPathFromAddress(address);
-        return (String [])getDevicePropertiesNative(objectPath);
-    }
-
-    /**
-     * Sets the remote device trust state.
-     *
-     * @return boolean to indicate operation success or fail
-     */
-    public synchronized boolean setTrust(String address, boolean value) {
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                    "Need BLUETOOTH_ADMIN permission");
-            return false;
-        }
-
-        if (!isEnabledInternal()) return false;
-
-        return setDevicePropertyBooleanNative(
-                getObjectPathFromAddress(address), "Trusted", value ? 1 : 0);
-    }
-
-    /**
-     * Gets the remote device trust state as boolean.
-     * Note: this value may be
-     * retrieved from cache if we retrieved the data before *
-     *
-     * @return boolean to indicate trusted or untrusted state
-     */
-    public synchronized boolean getTrustState(String address) {
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-            return false;
-        }
-
-        String val = mDeviceProperties.getProperty(address, "Trusted");
-        if (val == null) {
-            return false;
-        } else {
-            return val.equals("true");
-        }
-    }
-
-    /**
-     * Gets the remote major, minor classes encoded as a 32-bit
-     * integer.
-     *
-     * Note: this value is retrieved from cache, because we get it during
-     *       remote-device discovery.
-     *
-     * @return 32-bit integer encoding the remote major, minor, and service
-     *         classes.
-     */
-    public synchronized int getRemoteClass(String address) {
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-            return BluetoothClass.ERROR;
-        }
-        String val = mDeviceProperties.getProperty(address, "Class");
-        if (val == null)
-            return BluetoothClass.ERROR;
-        else {
-            return Integer.valueOf(val);
-        }
-    }
-
-
-    /**
-     * Gets the UUIDs supported by the remote device
-     *
-     * @return array of 128bit ParcelUuids
-     */
-    public synchronized ParcelUuid[] getRemoteUuids(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return null;
-        }
-        return getUuidFromCache(address);
-    }
-
-    ParcelUuid[] getUuidFromCache(String address) {
-        String value = mDeviceProperties.getProperty(address, "UUIDs");
-        if (value == null) return null;
-
-        String[] uuidStrings = null;
-        // The UUIDs are stored as a "," separated string.
-        uuidStrings = value.split(",");
-        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
-
-        for (int i = 0; i < uuidStrings.length; i++) {
-            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
-        }
-        return uuids;
-    }
-
-    /**
-     * Connect and fetch new UUID's using SDP.
-     * The UUID's found are broadcast as intents.
-     * Optionally takes a uuid and callback to fetch the RFCOMM channel for the
-     * a given uuid.
-     * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success
-     * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for
-     * callback and broadcast intents.
-     */
-    public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid,
-            IBluetoothCallback callback) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-
-        RemoteService service = new RemoteService(address, uuid);
-        if (uuid != null && mUuidCallbackTracker.get(service) != null) {
-            // An SDP query for this address & uuid is already in progress
-            // Do not add this callback for the uuid
-            return false;
-        }
-
-        if (mUuidIntentTracker.contains(address)) {
-            // An SDP query for this address is already in progress
-            // Add this uuid onto the in-progress SDP query
-            if (uuid != null) {
-                mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
-            }
-            return true;
-        }
-
-        // If the device is already created, we will
-        // do the SDP on the callback of createDeviceNative.
-        boolean ret= createDeviceNative(address);
-
-        mUuidIntentTracker.add(address);
-        if (uuid != null) {
-            mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
-        }
-
-        Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT);
-        message.obj = address;
-        mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY);
-        return ret;
-    }
-
-    /**
-     * Gets the rfcomm channel associated with the UUID.
-     * Pulls records from the cache only.
-     *
-     * @param address Address of the remote device
-     * @param uuid ParcelUuid of the service attribute
-     *
-     * @return rfcomm channel associated with the service attribute
-     *         -1 on error
-     */
-    public int getRemoteServiceChannel(String address, ParcelUuid uuid) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return -1;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return BluetoothDevice.ERROR;
-        }
-        // Check if we are recovering from a crash.
-        if (mDeviceProperties.isEmpty()) {
-            if (mDeviceProperties.updateCache(address) == null)
-                return -1;
-        }
-
-        Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address);
-        if (value != null && value.containsKey(uuid))
-            return value.get(uuid);
-        return -1;
-    }
-
-    public synchronized boolean setPin(String address, byte[] pin) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (pin == null || pin.length <= 0 || pin.length > 16 ||
-            !BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-        // bluez API wants pin as a string
-        String pinString;
-        try {
-            pinString = new String(pin, "UTF8");
-        } catch (UnsupportedEncodingException uee) {
-            Log.e(TAG, "UTF8 not supported?!?");
-            return false;
-        }
-        return setPinNative(address, pinString, data.intValue());
-    }
-
-    public synchronized boolean setPasskey(String address, int passkey) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-        return setPasskeyNative(address, passkey, data.intValue());
-    }
-
-    public synchronized boolean setPairingConfirmation(String address, boolean confirm) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-        return setPairingConfirmationNative(address, confirm, data.intValue());
-    }
-
-    public synchronized boolean setRemoteOutOfBandData(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-
-        Pair<byte[], byte[]> val = mDeviceOobData.get(address);
-        byte[] hash, randomizer;
-        if (val == null) {
-            // TODO: check what should be passed in this case.
-            hash = new byte[16];
-            randomizer = new byte[16];
-        } else {
-            hash = val.first;
-            randomizer = val.second;
-        }
-        return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue());
-    }
-
-    public synchronized boolean cancelPairingUserInput(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
-                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " +
-                "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " +
-                "by the remote or by bluez.\n");
-            return false;
-        }
-        return cancelPairingUserInputNative(address, data.intValue());
-    }
-
-    /*package*/ void updateDeviceServiceChannelCache(String address) {
-        if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")");
-
-        // We are storing the rfcomm channel numbers only for the uuids
-        // we are interested in.
-        ParcelUuid[] deviceUuids = getRemoteUuids(address);
-
-        ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>();
-
-        synchronized (this) {
-            for (RemoteService service : mUuidCallbackTracker.keySet()) {
-                if (service.address.equals(address)) {
-                    applicationUuids.add(service.uuid);
-                }
-            }
-        }
-
-        Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>();
-
-        // Retrieve RFCOMM channel for default uuids
-        for (ParcelUuid uuid : RFCOMM_UUIDS) {
-            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
-                int channel = getDeviceServiceChannelForUuid(address, uuid);
-                uuidToChannelMap.put(uuid, channel);
-                if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel);
-            }
-        }
-        // Retrieve RFCOMM channel for application requested uuids
-        for (ParcelUuid uuid : applicationUuids) {
-            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
-                int channel = getDeviceServiceChannelForUuid(address, uuid);
-                uuidToChannelMap.put(uuid, channel);
-                if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel);
-            }
-        }
-
-        synchronized (this) {
-            // Make application callbacks
-            for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator();
-                    iter.hasNext();) {
-                RemoteService service = iter.next();
-                if (service.address.equals(address)) {
-                    if (uuidToChannelMap.containsKey(service.uuid)) {
-                        int channel = uuidToChannelMap.get(service.uuid);
-
-                        if (DBG) Log.d(TAG, "Making callback for " + service.uuid +
-                                    " with result " + channel);
-                        IBluetoothCallback callback = mUuidCallbackTracker.get(service);
-                        if (callback != null) {
-                            try {
-                                callback.onRfcommChannelFound(channel);
-                            } catch (RemoteException e) {Log.e(TAG, "", e);}
-                        }
-
-                        iter.remove();
-                    }
-                }
-            }
-
-            // Update cache
-            mDeviceServiceChannelCache.put(address, uuidToChannelMap);
-        }
-    }
-
-    private int getDeviceServiceChannelForUuid(String address,
-            ParcelUuid uuid) {
-        return getDeviceServiceChannelNative(getObjectPathFromAddress(address),
-                uuid.toString(), 0x0004);
-    }
-
-    /**
-     * b is a handle to a Binder instance, so that this service can be notified
-     * for Applications that terminate unexpectedly, to clean there service
-     * records
-     */
-    public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid,
-            int channel, IBinder b) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return -1;
-
-        if (serviceName == null || uuid == null || channel < 1 ||
-                channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) {
-            return -1;
-        }
-        if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) {
-            Log.w(TAG, "Attempted to register a reserved UUID: " + uuid);
-            return -1;
-        }
-        int handle = addRfcommServiceRecordNative(serviceName,
-                uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(),
-                (short)channel);
-        if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle));
-        if (handle == -1) {
-            return -1;
-        }
-
-        ServiceRecordClient client = new ServiceRecordClient();
-        client.pid = Binder.getCallingPid();
-        client.binder = b;
-        client.death = new Reaper(handle, client.pid, RFCOMM_RECORD_REAPER);
-        mServiceRecordToPid.put(new Integer(handle), client);
-        try {
-            b.linkToDeath(client.death, 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            client.death = null;
-        }
-        return handle;
-    }
-
-    public void removeServiceRecord(int handle) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
-        // Since this is a binder call check if Bluetooth is off
-        if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
-        Message message = mHandler.obtainMessage(MESSAGE_REMOVE_SERVICE_RECORD);
-        message.obj = new Pair<Integer, Integer>(handle, Binder.getCallingPid());
-        mHandler.sendMessage(message);
-    }
-
-    private synchronized void checkAndRemoveRecord(int handle, int pid) {
-        ServiceRecordClient client = mServiceRecordToPid.get(handle);
-        if (client != null && pid == client.pid) {
-            if (DBG) Log.d(TAG, "Removing service record " +
-                Integer.toHexString(handle) + " for pid " + pid);
-
-            if (client.death != null) {
-                client.binder.unlinkToDeath(client.death, 0);
-            }
-
-            mServiceRecordToPid.remove(handle);
-            removeServiceRecordNative(handle);
-        }
-    }
-
-    private class Reaper implements IBinder.DeathRecipient {
-        int mPid;
-        int mHandle;
-        int mType;
-
-        Reaper(int handle, int pid, int type) {
-            mPid = pid;
-            mHandle = handle;
-            mType = type;
-        }
-
-        Reaper(int pid, int type) {
-            mPid = pid;
-            mType = type;
-        }
-
-        @Override
-        public void binderDied() {
-            synchronized (BluetoothService.this) {
-                if (DBG) Log.d(TAG, "Tracked app " + mPid + " died" + "Type:" + mType);
-                if (mType == RFCOMM_RECORD_REAPER) {
-                    checkAndRemoveRecord(mHandle, mPid);
-                } else if (mType == STATE_CHANGE_REAPER) {
-                    mStateChangeTracker.remove(mPid);
-                }
-            }
-        }
-    }
-
-
-    @Override
-    public boolean changeApplicationBluetoothState(boolean on,
-            IBluetoothStateChangeCallback callback, IBinder binder) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        int pid = Binder.getCallingPid();
-        //mStateChangeTracker is a synchronized map
-        if (!mStateChangeTracker.containsKey(pid)) {
-            if (on) {
-                mStateChangeTracker.put(pid, callback);
-            } else {
-                return false;
-            }
-        } else if (!on) {
-            mStateChangeTracker.remove(pid);
-        }
-
-        if (binder != null) {
-            try {
-                binder.linkToDeath(new Reaper(pid, STATE_CHANGE_REAPER), 0);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-                return false;
-            }
-        }
-
-        int type;
-        if (on) {
-            type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_ON;
-        } else {
-            type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_OFF;
-        }
-
-        mBluetoothState.sendMessage(type, callback);
-        return true;
-    }
-
-    boolean isApplicationStateChangeTrackerEmpty() {
-        return mStateChangeTracker.isEmpty();
-    }
-
-    void clearApplicationStateChangeTracker() {
-        mStateChangeTracker.clear();
-    }
-
-    Collection<IBluetoothStateChangeCallback> getApplicationStateChangeCallbacks() {
-        return mStateChangeTracker.values();
-    }
-
-    int getNumberOfApplicationStateChangeTrackers() {
-        return mStateChangeTracker.size();
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent == null) return;
-
-            String action = intent.getAction();
-            if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
-                ContentResolver resolver = context.getContentResolver();
-                // Query the airplane mode from Settings.System just to make sure that
-                // some random app is not sending this intent and disabling bluetooth
-                if (isAirplaneModeOn()) {
-                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON);
-                } else {
-                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF);
-                }
-            } else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
-                int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
-                if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state);
-                if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                    mDockAddress = null;
-                    mDockPin = null;
-                } else {
-                    SharedPreferences.Editor editor =
-                        mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
-                                mContext.MODE_PRIVATE).edit();
-                    editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true);
-                    editor.apply();
-                }
-            }
-        }
-    };
-
-    private void registerForAirplaneMode(IntentFilter filter) {
-        final ContentResolver resolver = mContext.getContentResolver();
-        final String airplaneModeRadios = Settings.System.getString(resolver,
-                Settings.System.AIRPLANE_MODE_RADIOS);
-        final String toggleableRadios = Settings.System.getString(resolver,
-                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
-
-        mIsAirplaneSensitive = airplaneModeRadios == null ? true :
-                airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
-        mIsAirplaneToggleable = toggleableRadios == null ? false :
-                toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH);
-
-        if (mIsAirplaneSensitive) {
-            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        }
-    }
-
-    /* Returns true if airplane mode is currently on */
-    /*package*/ final boolean isAirplaneModeOn() {
-        return Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
-    }
-
-    /* Broadcast the Uuid intent */
-    /*package*/ synchronized void sendUuidIntent(String address) {
-        ParcelUuid[] uuid = getUuidFromCache(address);
-        Intent intent = new Intent(BluetoothDevice.ACTION_UUID);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        mUuidIntentTracker.remove(address);
-    }
-
-    /*package*/ synchronized void makeServiceChannelCallbacks(String address) {
-        for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator();
-                iter.hasNext();) {
-            RemoteService service = iter.next();
-            if (service.address.equals(address)) {
-                if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: "
-                    + service.address + " " + service.uuid);
-                IBluetoothCallback callback = mUuidCallbackTracker.get(service);
-                if (callback != null) {
-                    try {
-                        callback.onRfcommChannelFound(-1);
-                    } catch (RemoteException e) {Log.e(TAG, "", e);}
-                }
-
-                iter.remove();
-            }
-        }
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
-        if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
-            return;
-        }
-
-        pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive);
-        pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable);
-
-        pw.println("Local address = " + getAddress());
-        pw.println("Local name = " + getName());
-        pw.println("isDiscovering() = " + isDiscovering());
-
-        mAdapter.getProfileProxy(mContext,
-                                 mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
-        mAdapter.getProfileProxy(mContext,
-                mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
-        mAdapter.getProfileProxy(mContext,
-                mBluetoothProfileServiceListener, BluetoothProfile.PAN);
-
-        dumpKnownDevices(pw);
-        dumpAclConnectedDevices(pw);
-        dumpHeadsetService(pw);
-        dumpInputDeviceProfile(pw);
-        dumpPanProfile(pw);
-        dumpApplicationServiceRecords(pw);
-        dumpProfileState(pw);
-    }
-
-    private void dumpProfileState(PrintWriter pw) {
-        pw.println("\n--Profile State dump--");
-        pw.println("\n Headset profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.HEADSET));
-        pw.println("\n A2dp profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.A2DP));
-        pw.println("\n HID profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.INPUT_DEVICE));
-        pw.println("\n PAN profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.PAN));
-    }
-
-    private void dumpHeadsetService(PrintWriter pw) {
-        pw.println("\n--Headset Service--");
-        if (mHeadsetProxy != null) {
-            List<BluetoothDevice> deviceList = mHeadsetProxy.getConnectedDevices();
-            if (deviceList.size() == 0) {
-                pw.println("No headsets connected");
-            } else {
-                BluetoothDevice device = deviceList.get(0);
-                pw.println("\ngetConnectedDevices[0] = " + device);
-                dumpHeadsetConnectionState(pw, device);
-                pw.println("getBatteryUsageHint() = " +
-                             mHeadsetProxy.getBatteryUsageHint(device));
-            }
-
-            deviceList.clear();
-            deviceList = mHeadsetProxy.getDevicesMatchingConnectionStates(new int[] {
-                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
-            pw.println("--Connected and Disconnected Headsets");
-            for (BluetoothDevice device: deviceList) {
-                pw.println(device);
-                if (mHeadsetProxy.isAudioConnected(device)) {
-                    pw.println("SCO audio connected to device:" + device);
-                }
-            }
-        }
-    }
-
-    private void dumpInputDeviceProfile(PrintWriter pw) {
-        pw.println("\n--Bluetooth Service- Input Device Profile");
-        if (mInputDevice != null) {
-            List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices();
-            if (deviceList.size() == 0) {
-                pw.println("No input devices connected");
-            } else {
-                pw.println("Number of connected devices:" + deviceList.size());
-                BluetoothDevice device = deviceList.get(0);
-                pw.println("getConnectedDevices[0] = " + device);
-                pw.println("Priority of Connected device = " + mInputDevice.getPriority(device));
-
-                switch (mInputDevice.getConnectionState(device)) {
-                    case BluetoothInputDevice.STATE_CONNECTING:
-                        pw.println("getConnectionState() = STATE_CONNECTING");
-                        break;
-                    case BluetoothInputDevice.STATE_CONNECTED:
-                        pw.println("getConnectionState() = STATE_CONNECTED");
-                        break;
-                    case BluetoothInputDevice.STATE_DISCONNECTING:
-                        pw.println("getConnectionState() = STATE_DISCONNECTING");
-                        break;
-                }
-            }
-            deviceList.clear();
-            deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] {
-                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
-            pw.println("--Connected and Disconnected input devices");
-            for (BluetoothDevice device: deviceList) {
-                pw.println(device);
-            }
-        }
-    }
-
-    private void dumpPanProfile(PrintWriter pw) {
-        pw.println("\n--Bluetooth Service- Pan Profile");
-        if (mPan != null) {
-            List<BluetoothDevice> deviceList = mPan.getConnectedDevices();
-            if (deviceList.size() == 0) {
-                pw.println("No Pan devices connected");
-            } else {
-                pw.println("Number of connected devices:" + deviceList.size());
-                BluetoothDevice device = deviceList.get(0);
-                pw.println("getConnectedDevices[0] = " + device);
-
-                switch (mPan.getConnectionState(device)) {
-                    case BluetoothInputDevice.STATE_CONNECTING:
-                        pw.println("getConnectionState() = STATE_CONNECTING");
-                        break;
-                    case BluetoothInputDevice.STATE_CONNECTED:
-                        pw.println("getConnectionState() = STATE_CONNECTED");
-                        break;
-                    case BluetoothInputDevice.STATE_DISCONNECTING:
-                        pw.println("getConnectionState() = STATE_DISCONNECTING");
-                        break;
-                }
-            }
-            deviceList.clear();
-            deviceList = mPan.getDevicesMatchingConnectionStates(new int[] {
-                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
-            pw.println("--Connected and Disconnected Pan devices");
-            for (BluetoothDevice device: deviceList) {
-                pw.println(device);
-            }
-        }
-    }
-
-    private void dumpHeadsetConnectionState(PrintWriter pw,
-            BluetoothDevice device) {
-        switch (mHeadsetProxy.getConnectionState(device)) {
-            case BluetoothHeadset.STATE_CONNECTING:
-                pw.println("getConnectionState() = STATE_CONNECTING");
-                break;
-            case BluetoothHeadset.STATE_CONNECTED:
-                pw.println("getConnectionState() = STATE_CONNECTED");
-                break;
-            case BluetoothHeadset.STATE_DISCONNECTING:
-                pw.println("getConnectionState() = STATE_DISCONNECTING");
-                break;
-            case BluetoothHeadset.STATE_AUDIO_CONNECTED:
-                pw.println("getConnectionState() = STATE_AUDIO_CONNECTED");
-                break;
-        }
-    }
-
-    private void dumpApplicationServiceRecords(PrintWriter pw) {
-        pw.println("\n--Application Service Records--");
-        for (Integer handle : mServiceRecordToPid.keySet()) {
-            Integer pid = mServiceRecordToPid.get(handle).pid;
-            pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
-        }
-    }
-
-    private void dumpAclConnectedDevices(PrintWriter pw) {
-        String[] devicesObjectPath = getKnownDevices();
-        pw.println("\n--ACL connected devices--");
-        if (devicesObjectPath != null) {
-            for (String device : devicesObjectPath) {
-                pw.println(getAddressFromObjectPath(device));
-            }
-        }
-    }
-
-    private void dumpKnownDevices(PrintWriter pw) {
-        pw.println("\n--Known devices--");
-        for (String address : mDeviceProperties.keySet()) {
-            int bondState = mBondState.getBondState(address);
-            pw.printf("%s %10s (%d) %s\n", address,
-                       toBondStateString(bondState),
-                       mBondState.getAttempt(address),
-                       getRemoteName(address));
-
-            Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address);
-            if (uuidChannels == null) {
-                pw.println("\tuuids = null");
-            } else {
-                for (ParcelUuid uuid : uuidChannels.keySet()) {
-                    Integer channel = uuidChannels.get(uuid);
-                    if (channel == null) {
-                        pw.println("\t" + uuid);
-                    } else {
-                        pw.println("\t" + uuid + " RFCOMM channel = " + channel);
-                    }
-                }
-            }
-            for (RemoteService service : mUuidCallbackTracker.keySet()) {
-                if (service.address.equals(address)) {
-                    pw.println("\tPENDING CALLBACK: " + service.uuid);
-                }
-            }
-        }
-    }
-
-    private void getProfileProxy() {
-        mAdapter.getProfileProxy(mContext,
-                                 mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
-    }
-
-    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = (BluetoothHeadset) proxy;
-            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
-                mInputDevice = (BluetoothInputDevice) proxy;
-            } else if (profile == BluetoothProfile.PAN) {
-                mPan = (BluetoothPan) proxy;
-            }
-        }
-        public void onServiceDisconnected(int profile) {
-            if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = null;
-            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
-                mInputDevice = null;
-            } else if (profile == BluetoothProfile.PAN) {
-                mPan = null;
-            }
-        }
-    };
-
-    /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) {
-        if (pairable && discoverable)
-            return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
-        else if (pairable && !discoverable)
-            return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
-        else
-            return BluetoothAdapter.SCAN_MODE_NONE;
-    }
-
-    /* package */ static String scanModeToBluezString(int mode) {
-        switch (mode) {
-        case BluetoothAdapter.SCAN_MODE_NONE:
-            return "off";
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-            return "connectable";
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-            return "discoverable";
-        }
-        return null;
-    }
-
-    /*package*/ String getAddressFromObjectPath(String objectPath) {
-        String adapterObjectPath = mAdapterProperties.getObjectPath();
-        if (adapterObjectPath == null || objectPath == null) {
-            Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath +
-                    "  or deviceObjectPath:" + objectPath + " is null");
-            return null;
-        }
-        if (!objectPath.startsWith(adapterObjectPath)) {
-            Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath +
-                    "  is not a prefix of deviceObjectPath:" + objectPath +
-                    "bluetoothd crashed ?");
-            return null;
-        }
-        String address = objectPath.substring(adapterObjectPath.length());
-        if (address != null) return address.replace('_', ':');
-
-        Log.e(TAG, "getAddressFromObjectPath: Address being returned is null");
-        return null;
-    }
-
-    /*package*/ String getObjectPathFromAddress(String address) {
-        String path = mAdapterProperties.getObjectPath();
-        if (path == null) {
-            Log.e(TAG, "Error: Object Path is null");
-            return null;
-        }
-        path = path + address.replace(":", "_");
-        return path;
-    }
-
-    /*package */ void setLinkTimeout(String address, int num_slots) {
-        String path = getObjectPathFromAddress(address);
-        boolean result = setLinkTimeoutNative(path, num_slots);
-
-        if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed");
-    }
-
-    /**** Handlers for PAN  Profile ****/
-    // TODO: This needs to be converted to a state machine.
-
-    public boolean isTetheringOn() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.isTetheringOn();
-        }
-    }
-
-    /*package*/boolean allowIncomingTethering() {
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.allowIncomingTethering();
-        }
-    }
-
-    public void setBluetoothTethering(boolean value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            mBluetoothPanProfileHandler.setBluetoothTethering(value);
-        }
-    }
-
-    public int getPanDeviceConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device);
-        }
-    }
-
-    public boolean connectPanDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-            "Need BLUETOOTH_ADMIN permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.connectPanDevice(device);
-        }
-    }
-
-    public List<BluetoothDevice> getConnectedPanDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.getConnectedPanDevices();
-        }
-    }
-
-    public List<BluetoothDevice> getPanDevicesMatchingConnectionStates(
-            int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states);
-        }
-    }
-
-    public boolean disconnectPanDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-            "Need BLUETOOTH_ADMIN permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.disconnectPanDevice(device);
-        }
-    }
-
-    /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             String iface,
-                                                             int state,
-                                                             int role) {
-        synchronized (mBluetoothPanProfileHandler) {
-            mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role);
-        }
-    }
-
-    /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             int state, int role) {
-        synchronized (mBluetoothPanProfileHandler) {
-            mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role);
-        }
-    }
-
-    /**** Handlers for Input Device Profile ****/
-    // This needs to be converted to state machine
-
-    public boolean connectInputDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.connectInputDevice(device, state);
-        }
-    }
-
-    public boolean connectInputDeviceInternal(BluetoothDevice device) {
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.connectInputDeviceInternal(device);
-        }
-    }
-
-    public boolean disconnectInputDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.disconnectInputDevice(device, state);
-        }
-    }
-
-    public boolean disconnectInputDeviceInternal(BluetoothDevice device) {
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
-        }
-    }
-
-    public int getInputDeviceConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
-        }
-    }
-
-    public List<BluetoothDevice> getConnectedInputDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getConnectedInputDevices();
-        }
-    }
-
-    public List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
-            int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
-        }
-    }
-
-
-    public int getInputDevicePriority(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getInputDevicePriority(device);
-        }
-    }
-
-    public boolean setInputDevicePriority(BluetoothDevice device, int priority) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority);
-        }
-    }
-
-    /**
-     * Handle incoming profile acceptance for profiles handled by Bluetooth Service,
-     * currently PAN and HID. This also is the catch all for all rejections for profiles
-     * that is not supported.
-     *
-     * @param device - Bluetooth Device
-     * @param allow - true / false
-     * @return
-     */
-    public boolean allowIncomingProfileConnect(BluetoothDevice device, boolean allow) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        String address = device.getAddress();
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-
-        Integer data = getAuthorizationAgentRequestData(address);
-        if (data == null) {
-            Log.w(TAG, "allowIncomingProfileConnect(" + device +
-                  ") called but no native data available");
-            return false;
-        }
-        if (DBG) log("allowIncomingProfileConnect: " + device + " : " + allow + " : " + data);
-        return setAuthorizationNative(address, allow, data.intValue());
-    }
-
-    /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
-        }
-    }
-
-    /*package*/void handleInputDevicePropertyChange(String address, boolean connected) {
-        synchronized (mBluetoothInputProfileHandler) {
-            mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected);
-        }
-    }
-
-    /**** Handlers for Health Device Profile ****/
-    // TODO: All these need to be converted to a state machine.
-
-    public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
-                                            IBluetoothHealthCallback callback) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-                return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback);
-        }
-    }
-
-    public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-                return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config);
-        }
-    }
-
-
-    public boolean connectChannelToSource(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.connectChannelToSource(device,
-                    config);
-        }
-    }
-
-    public boolean connectChannelToSink(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int channelType) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.connectChannel(device, config,
-                    channelType);
-        }
-    }
-
-    public boolean disconnectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int id) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.disconnectChannel(device, config, id);
-        }
-    }
-
-    public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.getMainChannelFd(device, config);
-        }
-    }
-
-    /*package*/ void onHealthDevicePropertyChanged(String devicePath,
-            String channelPath) {
-        synchronized (mBluetoothHealthProfileHandler) {
-            mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath,
-                    channelPath);
-        }
-    }
-
-    /*package*/ void onHealthDeviceChannelChanged(String devicePath,
-            String channelPath, boolean exists) {
-        synchronized(mBluetoothHealthProfileHandler) {
-            mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath,
-                    channelPath, exists);
-        }
-    }
-
-    /*package*/ void onHealthDeviceChannelConnectionError(int channelCode,
-            int newState) {
-        synchronized(mBluetoothHealthProfileHandler) {
-            mBluetoothHealthProfileHandler.onHealthDeviceChannelConnectionError(channelCode,
-                                                                                newState);
-        }
-    }
-
-    public int getHealthDeviceConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device);
-        }
-    }
-
-    public List<BluetoothDevice> getConnectedHealthDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.getConnectedHealthDevices();
-        }
-    }
-
-    public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(
-            int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.
-                    getHealthDevicesMatchingConnectionStates(states);
-        }
-    }
-
-    /*package*/boolean notifyIncomingHidConnection(String address) {
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state == null) {
-            return false;
-        }
-        Message msg = new Message();
-        msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING;
-        state.sendMessage(msg);
-        return true;
-    }
-
-    public boolean connectHeadset(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING;
-            msg.obj = state;
-            mHfpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean disconnectHeadset(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING;
-            msg.obj = state;
-            mHfpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean connectSink(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING;
-            msg.obj = state;
-            mA2dpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean disconnectSink(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING;
-            msg.obj = state;
-            mA2dpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) {
-        BluetoothDeviceProfileState state =
-            new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
-        mDeviceProfileState.put(address, state);
-        state.start();
-        return state;
-    }
-
-    void removeProfileState(String address) {
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state == null) return;
-
-        state.doQuit();
-        mDeviceProfileState.remove(address);
-    }
-
-    String[] getKnownDevices() {
-        String[] bonds = null;
-        String val = getProperty("Devices", true);
-        if (val != null) {
-            bonds = val.split(",");
-        }
-        return bonds;
-    }
-
-    private void initProfileState() {
-        String[] bonds = null;
-        String val = getProperty("Devices", false);
-        if (val != null) {
-            bonds = val.split(",");
-        }
-        if (bonds == null) {
-            return;
-        }
-        for (String path : bonds) {
-            String address = getAddressFromObjectPath(path);
-            BluetoothDeviceProfileState state = addProfileState(address, false);
-        }
-    }
-
-    private void autoConnect() {
-        synchronized (this) {
-            if (!mAllowConnect) {
-                Log.d(TAG, "Not auto-connecting devices because of temporary BT on state.");
-                return;
-            }
-        }
-
-        String[] bonds = getKnownDevices();
-        if (bonds == null) {
-            return;
-        }
-        for (String path : bonds) {
-            String address = getAddressFromObjectPath(path);
-            BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-            if (state != null) {
-                Message msg = new Message();
-                msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES;
-                state.sendMessage(msg);
-            }
-        }
-    }
-
-    public boolean notifyIncomingConnection(String address, boolean rejected) {
-        synchronized (this) {
-            if (!mAllowConnect) {
-                Log.d(TAG, "Not allowing incoming connection because of temporary BT on state.");
-                return false;
-            }
-        }
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            if (rejected) {
-                if (mA2dpService.getPriority(getRemoteDevice(address)) >=
-                    BluetoothProfile.PRIORITY_ON) {
-                    msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES;
-                    msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING;
-                    state.sendMessageDelayed(msg,
-                        BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY);
-                }
-            } else {
-                msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING;
-                state.sendMessage(msg);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /*package*/ boolean notifyIncomingA2dpConnection(String address, boolean rejected) {
-        synchronized (this) {
-            if (!mAllowConnect) {
-                Log.d(TAG, "Not allowing a2dp connection because of temporary BT on state.");
-                return false;
-            }
-        }
-
-       BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-       if (state != null) {
-           Message msg = new Message();
-           if (rejected) {
-               if (mHeadsetProxy.getPriority(getRemoteDevice(address)) >=
-                   BluetoothProfile.PRIORITY_ON) {
-                   msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES;
-                   msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING;
-                   state.sendMessageDelayed(msg,
-                             BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY);
-               }
-           } else {
-               msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING;
-               state.sendMessage(msg);
-           }
-           return true;
-       }
-       return false;
-    }
-
-    /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) {
-        mA2dpService = a2dpService;
-    }
-
-    /*package*/ Integer getAuthorizationAgentRequestData(String address) {
-        Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address);
-        return data;
-    }
-
-    public void sendProfileStateMessage(int profile, int cmd) {
-        Message msg = new Message();
-        msg.what = cmd;
-        if (profile == BluetoothProfileState.HFP) {
-            mHfpProfileState.sendMessage(msg);
-        } else if (profile == BluetoothProfileState.A2DP) {
-            mA2dpProfileState.sendMessage(msg);
-        }
-    }
-
-    public int getAdapterConnectionState() {
-        return mAdapterConnectionState;
-    }
-
-    public int getProfileConnectionState(int profile) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        Pair<Integer, Integer> state = mProfileConnectionState.get(profile);
-        if (state == null) return BluetoothProfile.STATE_DISCONNECTED;
-
-        return state.first;
-    }
-
-    private void updateProfileConnectionState(int profile, int newState, int oldState) {
-        // mProfileConnectionState is a hashmap -
-        // <Integer, Pair<Integer, Integer>>
-        // The key is the profile, the value is a pair. first element
-        // is the state and the second element is the number of devices
-        // in that state.
-        int numDev = 1;
-        int newHashState = newState;
-        boolean update = true;
-
-        // The following conditions are considered in this function:
-        // 1. If there is no record of profile and state - update
-        // 2. If a new device's state is current hash state - increment
-        //    number of devices in the state.
-        // 3. If a state change has happened to Connected or Connecting
-        //    (if current state is not connected), update.
-        // 4. If numDevices is 1 and that device state is being updated, update
-        // 5. If numDevices is > 1 and one of the devices is changing state,
-        //    decrement numDevices but maintain oldState if it is Connected or
-        //    Connecting
-        Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
-        if (stateNumDev != null) {
-            int currHashState = stateNumDev.first;
-            numDev = stateNumDev.second;
-
-            if (newState == currHashState) {
-                numDev ++;
-            } else if (newState == BluetoothProfile.STATE_CONNECTED ||
-                   (newState == BluetoothProfile.STATE_CONNECTING &&
-                    currHashState != BluetoothProfile.STATE_CONNECTED)) {
-                 numDev = 1;
-            } else if (numDev == 1 && oldState == currHashState) {
-                 update = true;
-            } else if (numDev > 1 && oldState == currHashState) {
-                 numDev --;
-
-                 if (currHashState == BluetoothProfile.STATE_CONNECTED ||
-                     currHashState == BluetoothProfile.STATE_CONNECTING) {
-                    newHashState = currHashState;
-                 }
-            } else {
-                 update = false;
-            }
-        }
-
-        if (update) {
-            mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState,
-                    numDev));
-        }
-    }
-
-    public synchronized void sendConnectionStateChange(BluetoothDevice
-            device, int profile, int state, int prevState) {
-        // Since this is a binder call check if Bluetooth is on still
-        if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
-
-        if (!validateProfileConnectionState(state) ||
-                !validateProfileConnectionState(prevState)) {
-            // Previously, an invalid state was broadcast anyway,
-            // with the invalid state converted to -1 in the intent.
-            // Better to log an error and not send an intent with
-            // invalid contents or set mAdapterConnectionState to -1.
-            Log.e(TAG, "Error in sendConnectionStateChange: "
-                    + "prevState " + prevState + " state " + state);
-            return;
-        }
-
-        updateProfileConnectionState(profile, state, prevState);
-
-        if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
-            mAdapterConnectionState = state;
-
-            if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED);
-            }
-
-            Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
-                    convertToAdapterState(state));
-            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
-                    convertToAdapterState(prevState));
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-            Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
-                    + prevState + " -> " + state);
-        }
-    }
-
-    private boolean validateProfileConnectionState(int state) {
-        return (state == BluetoothProfile.STATE_DISCONNECTED ||
-                state == BluetoothProfile.STATE_CONNECTING ||
-                state == BluetoothProfile.STATE_CONNECTED ||
-                state == BluetoothProfile.STATE_DISCONNECTING);
-    }
-
-    private int convertToAdapterState(int state) {
-        switch (state) {
-            case BluetoothProfile.STATE_DISCONNECTED:
-                return BluetoothAdapter.STATE_DISCONNECTED;
-            case BluetoothProfile.STATE_DISCONNECTING:
-                return BluetoothAdapter.STATE_DISCONNECTING;
-            case BluetoothProfile.STATE_CONNECTED:
-                return BluetoothAdapter.STATE_CONNECTED;
-            case BluetoothProfile.STATE_CONNECTING:
-                return BluetoothAdapter.STATE_CONNECTING;
-        }
-        Log.e(TAG, "Error in convertToAdapterState");
-        return -1;
-    }
-
-    private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
-        switch (prevState) {
-            case BluetoothProfile.STATE_CONNECTING:
-                mProfilesConnecting--;
-                break;
-
-            case BluetoothProfile.STATE_CONNECTED:
-                mProfilesConnected--;
-                break;
-
-            case BluetoothProfile.STATE_DISCONNECTING:
-                mProfilesDisconnecting--;
-                break;
-        }
-
-        switch (state) {
-            case BluetoothProfile.STATE_CONNECTING:
-                mProfilesConnecting++;
-                return (mProfilesConnected == 0 && mProfilesConnecting == 1);
-
-            case BluetoothProfile.STATE_CONNECTED:
-                mProfilesConnected++;
-                return (mProfilesConnected == 1);
-
-            case BluetoothProfile.STATE_DISCONNECTING:
-                mProfilesDisconnecting++;
-                return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
-
-            case BluetoothProfile.STATE_DISCONNECTED:
-                return (mProfilesConnected == 0 && mProfilesConnecting == 0);
-
-            default:
-                return true;
-        }
-    }
-
-    private void createIncomingConnectionStateFile() {
-        File f = new File(INCOMING_CONNECTION_FILE);
-        if (!f.exists()) {
-            try {
-                f.createNewFile();
-            } catch (IOException e) {
-                Log.e(TAG, "IOException: cannot create file");
-            }
-        }
-    }
-
-    /** @hide */
-    public Pair<Integer, String> getIncomingState(String address) {
-        if (mIncomingConnections.isEmpty()) {
-            createIncomingConnectionStateFile();
-            readIncomingConnectionState();
-        }
-        return mIncomingConnections.get(address);
-    }
-
-    private void readIncomingConnectionState() {
-        synchronized(mIncomingConnections) {
-            FileInputStream fstream = null;
-            try {
-              fstream = new FileInputStream(INCOMING_CONNECTION_FILE);
-              DataInputStream in = new DataInputStream(fstream);
-              BufferedReader file = new BufferedReader(new InputStreamReader(in));
-              String line;
-              while((line = file.readLine()) != null) {
-                  line = line.trim();
-                  if (line.length() == 0) continue;
-                  String[] value = line.split(",");
-                  if (value != null && value.length == 3) {
-                      Integer val1 = Integer.parseInt(value[1]);
-                      Pair<Integer, String> val = new Pair(val1, value[2]);
-                      mIncomingConnections.put(value[0], val);
-                  }
-              }
-            } catch (FileNotFoundException e) {
-                log("FileNotFoundException: readIncomingConnectionState" + e.toString());
-            } catch (IOException e) {
-                log("IOException: readIncomingConnectionState" + e.toString());
-            } finally {
-                if (fstream != null) {
-                    try {
-                        fstream.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-        }
-    }
-
-    private void truncateIncomingConnectionFile() {
-        RandomAccessFile r = null;
-        try {
-            r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw");
-            r.setLength(0);
-        } catch (FileNotFoundException e) {
-            log("FileNotFoundException: truncateIncomingConnectionState" + e.toString());
-        } catch (IOException e) {
-            log("IOException: truncateIncomingConnectionState" + e.toString());
-        } finally {
-            if (r != null) {
-                try {
-                    r.close();
-                } catch (IOException e) {
-                    // ignore
-                 }
-            }
-        }
-    }
-
-    /** @hide */
-    public void writeIncomingConnectionState(String address, Pair<Integer, String> data) {
-        synchronized(mIncomingConnections) {
-            mIncomingConnections.put(address, data);
-
-            truncateIncomingConnectionFile();
-            BufferedWriter out = null;
-            StringBuilder value = new StringBuilder();
-            try {
-                out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true));
-                for (String devAddress: mIncomingConnections.keySet()) {
-                  Pair<Integer, String> val = mIncomingConnections.get(devAddress);
-                  value.append(devAddress);
-                  value.append(",");
-                  value.append(val.first.toString());
-                  value.append(",");
-                  value.append(val.second);
-                  value.append("\n");
-                }
-                out.write(value.toString());
-            } catch (FileNotFoundException e) {
-                log("FileNotFoundException: writeIncomingConnectionState" + e.toString());
-            } catch (IOException e) {
-                log("IOException: writeIncomingConnectionState" + e.toString());
-            } finally {
-                if (out != null) {
-                    try {
-                        out.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private native static void classInitNative();
-    private native void initializeNativeDataNative();
-    private native boolean setupNativeDataNative();
-    private native boolean tearDownNativeDataNative();
-    private native void cleanupNativeDataNative();
-    /*package*/ native String getAdapterPathNative();
-
-    private native int isEnabledNative();
-    /*package*/ native int enableNative();
-    /*package*/ native int disableNative();
-
-    /*package*/ native Object[] getAdapterPropertiesNative();
-    private native Object[] getDevicePropertiesNative(String objectPath);
-    private native boolean setAdapterPropertyStringNative(String key, String value);
-    private native boolean setAdapterPropertyIntegerNative(String key, int value);
-    private native boolean setAdapterPropertyBooleanNative(String key, int value);
-
-    private native boolean startDiscoveryNative();
-    private native boolean stopDiscoveryNative();
-
-    private native boolean createPairedDeviceNative(String address, int timeout_ms);
-    private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms);
-    private native byte[] readAdapterOutOfBandDataNative();
-
-    private native boolean cancelDeviceCreationNative(String address);
-    private native boolean removeDeviceNative(String objectPath);
-    private native int getDeviceServiceChannelNative(String objectPath, String uuid,
-            int attributeId);
-
-    private native boolean cancelPairingUserInputNative(String address, int nativeData);
-    private native boolean setPinNative(String address, String pin, int nativeData);
-    private native boolean setPasskeyNative(String address, int passkey, int nativeData);
-    private native boolean setPairingConfirmationNative(String address, boolean confirm,
-            int nativeData);
-    private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash,
-                                                        byte[] randomizer, int nativeData);
-
-    private native boolean setDevicePropertyBooleanNative(String objectPath, String key,
-            int value);
-    private native boolean setDevicePropertyStringNative(String objectPath, String key,
-            String value);
-    private native boolean createDeviceNative(String address);
-    /*package*/ native boolean discoverServicesNative(String objectPath, String pattern);
-
-    private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb,
-            short channel);
-    private native boolean removeServiceRecordNative(int handle);
-    private native boolean setLinkTimeoutNative(String path, int num_slots);
-
-    native boolean connectInputDeviceNative(String path);
-    native boolean disconnectInputDeviceNative(String path);
-
-    native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
-    native boolean connectPanDeviceNative(String path, String dstRole);
-    native boolean disconnectPanDeviceNative(String path);
-    native boolean disconnectPanServerDeviceNative(String path,
-            String address, String iface);
-
-    private native int[] addReservedServiceRecordsNative(int[] uuuids);
-    private native boolean removeReservedServiceRecordsNative(int[] handles);
-
-    // Health API
-    native String registerHealthApplicationNative(int dataType, String role, String name,
-            String channelType);
-    native String registerHealthApplicationNative(int dataType, String role, String name);
-    native boolean unregisterHealthApplicationNative(String path);
-    native boolean createChannelNative(String devicePath, String appPath, String channelType,
-                                       int code);
-    native boolean destroyChannelNative(String devicePath, String channelpath, int code);
-    native String getMainChannelNative(String path);
-    native String getChannelApplicationNative(String channelPath);
-    native ParcelFileDescriptor getChannelFdNative(String channelPath);
-    native boolean releaseChannelFdNative(String channelPath);
-    native boolean setAuthorizationNative(String address, boolean value, int data);
-}
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index c783e6a..2411cec 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -29,9 +29,12 @@
 import android.content.IntentFilter;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
+import android.os.Binder;
 import android.os.Process;
+import android.os.UserId;
 import android.provider.Settings;
 import android.util.Log;
+import android.util.SparseArray;
 
 import java.util.List;
 
@@ -48,7 +51,7 @@
     private final Context mContext;
 
     // This field is initialized lazily in getSearchables(), and then never modified.
-    private Searchables mSearchables;
+    private SparseArray<Searchables> mSearchables;
 
     private ContentObserver mGlobalSearchObserver;
 
@@ -66,14 +69,24 @@
                 mContext.getContentResolver());
     }
 
-    private synchronized Searchables getSearchables() {
+    private synchronized Searchables getSearchables(int userId) {
         if (mSearchables == null) {
-            Log.i(TAG, "Building list of searchable activities");
             new MyPackageMonitor().register(mContext, null, true);
-            mSearchables = new Searchables(mContext);
-            mSearchables.buildSearchableList();
+            mSearchables = new SparseArray<Searchables>();
         }
-        return mSearchables;
+        Searchables searchables = mSearchables.get(userId);
+
+        long origId = Binder.clearCallingIdentity();
+        boolean userExists = mContext.getPackageManager().getUser(userId) != null;
+        Binder.restoreCallingIdentity(origId);
+
+        if (searchables == null && userExists) {
+            Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+            searchables = new Searchables(mContext, userId);
+            searchables.buildSearchableList();
+            mSearchables.append(userId, searchables);
+        }
+        return searchables;
     }
 
     /**
@@ -87,7 +100,7 @@
                 public void run() {
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     mContext.unregisterReceiver(BootCompletedReceiver.this);
-                    getSearchables();
+                    getSearchables(0);
                 }
             }.start();
         }
@@ -109,8 +122,12 @@
         }
 
         private void updateSearchables() {
-            // Update list of searchable activities
-            getSearchables().buildSearchableList();
+            synchronized (SearchManagerService.this) {
+                // Update list of searchable activities
+                for (int i = 0; i < mSearchables.size(); i++) {
+                    getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+                }
+            }
             // Inform all listeners that the list of searchables has been updated.
             Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
@@ -132,7 +149,11 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            getSearchables().buildSearchableList();
+            synchronized (SearchManagerService.this) {
+                for (int i = 0; i < mSearchables.size(); i++) {
+                    getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+                }
+            }
             Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
             mContext.sendBroadcast(intent);
@@ -156,32 +177,32 @@
             Log.e(TAG, "getSearchableInfo(), activity == null");
             return null;
         }
-        return getSearchables().getSearchableInfo(launchActivity);
+        return getSearchables(UserId.getCallingUserId()).getSearchableInfo(launchActivity);
     }
 
     /**
      * Returns a list of the searchable activities that can be included in global search.
      */
     public List<SearchableInfo> getSearchablesInGlobalSearch() {
-        return getSearchables().getSearchablesInGlobalSearchList();
+        return getSearchables(UserId.getCallingUserId()).getSearchablesInGlobalSearchList();
     }
 
     public List<ResolveInfo> getGlobalSearchActivities() {
-        return getSearchables().getGlobalSearchActivities();
+        return getSearchables(UserId.getCallingUserId()).getGlobalSearchActivities();
     }
 
     /**
      * Gets the name of the global search activity.
      */
     public ComponentName getGlobalSearchActivity() {
-        return getSearchables().getGlobalSearchActivity();
+        return getSearchables(UserId.getCallingUserId()).getGlobalSearchActivity();
     }
 
     /**
      * Gets the name of the web search activity.
      */
     public ComponentName getWebSearchActivity() {
-        return getSearchables().getWebSearchActivity();
+        return getSearchables(UserId.getCallingUserId()).getWebSearchActivity();
     }
 
 }
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index f24d52f..4e00ef9 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,6 +16,7 @@
 
 package android.server.search;
 
+import android.app.AppGlobals;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
 import android.content.ComponentName;
@@ -23,9 +24,11 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -38,6 +41,7 @@
 
 /**
  * This class maintains the information about all searchable activities.
+ * This is a hidden class.
  */
 public class Searchables {
 
@@ -65,12 +69,18 @@
     public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
             "com.google.android.providers.enhancedgooglesearch/.Launcher";
 
+    // Cache the package manager instance
+    private IPackageManager mPm;
+    // User for which this Searchables caches information
+    private int mUserId;
+
     /**
      *
      * @param context Context to use for looking up activities etc.
      */
-    public Searchables (Context context) {
+    public Searchables (Context context, int userId) {
         mContext = context;
+        mUserId = userId;
     }
 
     /**
@@ -195,16 +205,14 @@
         ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
                                 = new ArrayList<SearchableInfo>();
 
-        final PackageManager pm = mContext.getPackageManager();
-
         // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
         List<ResolveInfo> searchList;
         final Intent intent = new Intent(Intent.ACTION_SEARCH);
-        searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+        searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
 
         List<ResolveInfo> webSearchInfoList;
         final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
-        webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+        webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
 
         // analyze each one, generate a Searchables record, and record
         if (searchList != null || webSearchInfoList != null) {
@@ -262,10 +270,8 @@
         // Step 1 : Query the package manager for a list
         // of activities that can handle the GLOBAL_SEARCH intent.
         Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
-        PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
-                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
+                    queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
         if (activities != null && !activities.isEmpty()) {
             // Step 2: Rank matching activities according to our heuristics.
             Collections.sort(activities, GLOBAL_SEARCH_RANKER);
@@ -301,10 +307,8 @@
         Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
         intent.setComponent(globalSearch);
 
-        PackageManager pm = mContext.getPackageManager();
-        List<ResolveInfo> activities =
-                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
+        List<ResolveInfo> activities = queryIntentActivities(intent,
+                PackageManager.MATCH_DEFAULT_ONLY);
         if (activities != null && !activities.isEmpty()) {
             return true;
         }
@@ -374,9 +378,8 @@
         }
         Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
         intent.setPackage(globalSearchActivity.getPackageName());
-        PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
-                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+                queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
 
         if (activities != null && !activities.isEmpty()) {
             ActivityInfo ai = activities.get(0).activityInfo;
@@ -387,6 +390,22 @@
         return null;
     }
 
+    private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+        if (mPm == null) {
+            mPm = AppGlobals.getPackageManager();
+        }
+        List<ResolveInfo> activities = null;
+        try {
+            activities =
+                    mPm.queryIntentActivities(intent,
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                    flags, mUserId);
+        } catch (RemoteException re) {
+            // Local call
+        }
+        return activities;
+    }
+
     /**
      * Returns the list of searchable activities.
      */
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 3e0942c..f8501a9 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -98,6 +98,7 @@
     private static final int MSG_WALLPAPER_OFFSETS = 10020;
     private static final int MSG_WALLPAPER_COMMAND = 10025;
     private static final int MSG_WINDOW_RESIZED = 10030;
+    private static final int MSG_WINDOW_MOVED = 10035;
     private static final int MSG_TOUCH_EVENT = 10040;
     
     private Looper mCallbackLooper;
@@ -259,7 +260,13 @@
                         reportDraw ? 1 : 0);
                 mCaller.sendMessage(msg);
             }
-            
+
+            @Override
+            public void moved(int newX, int newY) {
+                Message msg = mCaller.obtainMessageII(MSG_WINDOW_MOVED, newX, newY);
+                mCaller.sendMessage(msg);
+            }
+
             @Override
             public void dispatchAppVisibility(boolean visible) {
                 // We don't do this in preview mode; we'll let the preview
@@ -290,7 +297,8 @@
                     }
                 }
             }
-            
+
+            @Override
             public void dispatchWallpaperCommand(String action, int x, int y,
                     int z, Bundle extras, boolean sync) {
                 synchronized (mLock) {
@@ -599,7 +607,7 @@
 
                     if (!mCreated) {
                         mLayout.type = mIWallpaperEngine.mWindowType;
-                        mLayout.gravity = Gravity.LEFT|Gravity.TOP;
+                        mLayout.gravity = Gravity.START|Gravity.TOP;
                         mLayout.setTitle(WallpaperService.this.getClass().getName());
                         mLayout.windowAnimations =
                                 com.android.internal.R.style.Animation_Wallpaper;
@@ -1044,6 +1052,9 @@
                     mEngine.updateSurface(true, false, reportDraw);
                     mEngine.doOffsetsChanged(true);
                 } break;
+                case MSG_WINDOW_MOVED: {
+                    // Do nothing. What does it mean for a Wallpaper to move?
+                } break;
                 case MSG_TOUCH_EVENT: {
                     boolean skip = false;
                     MotionEvent ev = (MotionEvent)message.obj;
diff --git a/core/java/android/text/Spanned.java b/core/java/android/text/Spanned.java
index 2b73763..b4622e0 100644
--- a/core/java/android/text/Spanned.java
+++ b/core/java/android/text/Spanned.java
@@ -30,8 +30,19 @@
      * of spans.
      *
      * MARK and POINT are conceptually located <i>between</i> two adjacent characters.
-     * A MARK is "attached" to the character on the left hand side, while a POINT
-     * tends to stick to the character on the right hand side.
+     * A MARK is "attached" to the character before, while a POINT will stick to the character
+     * after. The insertion cursor is conceptually located between the MARK and the POINT.
+     *
+     * As a result, inserting a new character between a MARK and a POINT will leave the MARK
+     * unchanged, while the POINT will be shifted, now located after the inserted character and
+     * still glued to the same character after it.
+     *
+     * Depending on whether the insertion happens at the beginning or the end of a span, the span
+     * will hence be expanded to <i>include</i> the new character (when the span is using a MARK at
+     * its beginning or a POINT at its end) or it will be <i>excluded</i>.
+     *
+     * Note that <i>before</i> and <i>after</i> here refer to offsets in the String, which are
+     * independent from the visual representation of the text (left-to-right or right-to-left).
      */
     public static final int SPAN_POINT_MARK_MASK = 0x33;
     
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6a619af..ac3dee4 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -150,8 +150,8 @@
 
         mColumns = COLUMNS_ELLIPSIZE;
         mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
-        mLineDirections = new Directions[
-                             ArrayUtils.idealIntArraySize(2 * mColumns)];
+        mLineDirections = new Directions[ArrayUtils.idealIntArraySize(2 * mColumns)];
+        // FIXME This is never recycled
         mMeasured = MeasuredText.obtain();
     }
 
@@ -340,7 +340,9 @@
                         w += widths[j - paraStart];
                     }
 
-                    if (w <= width) {
+                    boolean isSpaceOrTab = c == CHAR_SPACE || c == CHAR_TAB;
+
+                    if (w <= width || isSpaceOrTab) {
                         fitWidth = w;
                         fit = j + 1;
 
@@ -353,30 +355,22 @@
                         if (fmBottom > fitBottom)
                             fitBottom = fmBottom;
 
-                        /*
-                         * From the Unicode Line Breaking Algorithm:
-                         * (at least approximately)
-                         *
-                         * .,:; are class IS: breakpoints
-                         *      except when adjacent to digits
-                         * /    is class SY: a breakpoint
-                         *      except when followed by a digit.
-                         * -    is class HY: a breakpoint
-                         *      except when followed by a digit.
-                         *
-                         * Ideographs are class ID: breakpoints when adjacent,
-                         * except for NS (non-starters), which can be broken
-                         * after but not before.
-                         */
-                        if (c == CHAR_SPACE || c == CHAR_TAB ||
-                            ((c == CHAR_DOT || c == CHAR_COMMA ||
-                                    c == CHAR_COLON || c == CHAR_SEMICOLON) &&
-                             (j - 1 < here || !Character.isDigit(chs[j - 1 - paraStart])) &&
-                             (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
-                            ((c == CHAR_SLASH || c == CHAR_HYPHEN) &&
-                             (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
-                            (c >= CHAR_FIRST_CJK && isIdeographic(c, true) &&
-                             j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false))) {
+                        // From the Unicode Line Breaking Algorithm (at least approximately)
+                        boolean isLineBreak = isSpaceOrTab ||
+                                // .,:; are class IS breakpoints, except when adjacent to digits
+                                ((c == CHAR_DOT || c == CHAR_COMMA ||
+                                c == CHAR_COLON || c == CHAR_SEMICOLON) &&
+                                (j - 1 < here || !Character.isDigit(chs[j - 1 - paraStart])) &&
+                                (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
+                                // / is class SY and - is class HY, except when followed by a digit
+                                ((c == CHAR_SLASH || c == CHAR_HYPHEN) &&
+                                (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
+                                // Ideographs are class ID: breakpoints when adjacent, except for NS
+                                // (non-starters), which can be broken after but not before
+                                (c >= CHAR_FIRST_CJK && isIdeographic(c, true) &&
+                                j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false));
+
+                        if (isLineBreak) {
                             okWidth = w;
                             ok = j + 1;
 
@@ -396,13 +390,6 @@
                         float currentTextWidth;
 
                         if (ok != here) {
-                            // If it is a space that makes the length exceed width, cut here
-                            if (c == CHAR_SPACE) ok = j + 1;
-
-                            while (ok < spanEnd && chs[ok - paraStart] == CHAR_SPACE) {
-                                ok++;
-                            }
-
                             endPos = ok;
                             above = okAscent;
                             below = okDescent;
@@ -450,10 +437,10 @@
                             spanEnd = here;
                             break;
                         }
-                    }
-                    // FIXME This should be moved in the above else block which changes mLineCount
-                    if (mLineCount >= mMaximumVisibleLineCount) {
-                        break;
+
+                        if (mLineCount >= mMaximumVisibleLineCount) {
+                            break;
+                        }
                     }
                 }
             }
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index be2840b..bbaa173 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -22,6 +22,7 @@
 
 /**
  * Some objects that implement TextDirectionHeuristic.
+ *
  * @hide
  */
 public class TextDirectionHeuristics {
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
index 93f5cd3..60526e1 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -24,7 +24,6 @@
 /**
  * Various utilities for Locales
  *
- * @hide
  */
 public class LocaleUtil {
 
@@ -41,8 +40,7 @@
      * {@link View#LAYOUT_DIRECTION_LTR} or
      * {@link View#LAYOUT_DIRECTION_RTL}.
      *
-     * Warning: this code does not support vertical scripts.
-     * @hide
+     * Be careful: this code will need to be updated when vertical scripts will be supported
      */
     public static int getLayoutDirectionFromLocale(Locale locale) {
         if (locale != null && !locale.equals(Locale.ROOT)) {
@@ -68,7 +66,8 @@
      * {@link View#LAYOUT_DIRECTION_LTR} or
      * {@link View#LAYOUT_DIRECTION_RTL}.
      *
-     * Warning: this code does not support vertical scripts.
+     * Be careful: this code will need to be updated when vertical scripts will be supported
+     *
      * @hide
      */
     private static int getLayoutDirectionFromFirstChar(Locale locale) {
diff --git a/core/java/android/util/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java
new file mode 100755
index 0000000..eb9c47d
--- /dev/null
+++ b/core/java/android/util/PropertyValueModel.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * A value model for a {@link Property property} of a host object. This class can be used for
+ * both reflective and non-reflective property implementations.
+ *
+ * @param <H> the host type, where the host is the object that holds this property
+ * @param <T> the value type
+ *
+ * @see Property
+ * @see ValueModel
+ */
+public class PropertyValueModel<H, T> extends ValueModel<T> {
+    private final H mHost;
+    private final Property<H, T> mProperty;
+
+    private PropertyValueModel(H host, Property<H, T> property) {
+        mProperty = property;
+        mHost = host;
+    }
+
+    /**
+     * Returns the host.
+     *
+     * @return the host
+     */
+    public H getHost() {
+        return mHost;
+    }
+
+    /**
+     * Returns the property.
+     *
+     * @return the property
+     */
+    public Property<H, T> getProperty() {
+        return mProperty;
+    }
+
+    @Override
+    public Class<T> getType() {
+        return mProperty.getType();
+    }
+
+    @Override
+    public T get() {
+        return mProperty.get(mHost);
+    }
+
+    @Override
+    public void set(T value) {
+        mProperty.set(mHost, value);
+    }
+
+    /**
+     * Return an appropriate PropertyValueModel for this host and property.
+     *
+     * @param host the host
+     * @param property the property
+     * @return the value model
+     */
+    public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) {
+        return new PropertyValueModel<H, T>(host, property);
+    }
+
+    /**
+     * Return a PropertyValueModel for this {@code host} and a
+     * reflective property, constructed from this {@code propertyType} and {@code propertyName}.
+     *
+     * @param host
+     * @param propertyType the property type
+     * @param propertyName the property name
+     * @return a value model with this host and a reflective property with this type and name
+     *
+     * @see Property#of
+     */
+    public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType,
+            String propertyName) {
+        return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName));
+    }
+
+    private static Class getNullaryMethodReturnType(Class c, String name) {
+        try {
+            return c.getMethod(name).getReturnType();
+        } catch (NoSuchMethodException e) {
+            return null;
+        }
+    }
+
+    private static Class getFieldType(Class c, String name) {
+        try {
+            return c.getField(name).getType();
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+
+    private static String capitalize(String name) {
+        if (name.isEmpty()) {
+            return name;
+        }
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+    }
+
+    /**
+     * Return a PropertyValueModel for this {@code host} and and {@code propertyName}.
+     *
+     * @param host the host
+     * @param propertyName the property name
+     * @return a value model with this host and a reflective property with this name
+     */
+    public static PropertyValueModel of(Object host, String propertyName) {
+        Class clazz = host.getClass();
+        String suffix = capitalize(propertyName);
+        Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix);
+        if (propertyType == null) {
+            propertyType = getNullaryMethodReturnType(clazz, "is" + suffix);
+        } 
+        if (propertyType == null) {
+            propertyType = getFieldType(clazz, propertyName); 
+        }         
+        if (propertyType == null) {
+            throw new NoSuchPropertyException(propertyName); 
+        }
+        return of(host, propertyType, propertyName);
+    }
+}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index c4ebec4..7d33ff4a 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -18,8 +18,10 @@
 
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.text.format.DateUtils;
 
-import libcore.util.ZoneInfoDB;
+import com.android.internal.util.XmlUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -28,10 +30,10 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
-import java.util.TimeZone;
 import java.util.Date;
+import java.util.TimeZone;
 
-import com.android.internal.util.XmlUtils;
+import libcore.util.ZoneInfoDB;
 
 /**
  * A class containing utility methods related to time zones.
@@ -245,6 +247,8 @@
     private static final Object sFormatSync = new Object();
     private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
 
+    private static final long LARGEST_DURATION = (1000 * DateUtils.DAY_IN_MILLIS) - 1;
+
     static private int accumField(int amt, int suffix, boolean always, int zeropad) {
         if (amt > 99 || (always && zeropad >= 3)) {
             return 3+suffix;
@@ -307,6 +311,10 @@
             duration = -duration;
         }
 
+        if (duration > LARGEST_DURATION) {
+            duration = LARGEST_DURATION;
+        }
+
         int millis = (int)(duration%1000);
         int seconds = (int) Math.floor(duration / 1000);
         int days = 0, hours = 0, minutes = 0;
diff --git a/core/java/android/util/ValueModel.java b/core/java/android/util/ValueModel.java
new file mode 100755
index 0000000..4789682
--- /dev/null
+++ b/core/java/android/util/ValueModel.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * A ValueModel is an abstraction for a 'slot' or place in memory in which a value
+ * may be stored and retrieved. A common implementation of ValueModel is a regular property of
+ * an object, whose value may be retrieved by calling the appropriate <em>getter</em>
+ * method and set by calling the corresponding <em>setter</em> method.
+ *
+ * @param <T> the value type
+ *
+ * @see PropertyValueModel
+ */
+public abstract class ValueModel<T> {
+    /**
+     * The empty model should be used in place of {@code null} to indicate that a
+     * model has not been set. The empty model has no value and does nothing when it is set.
+     */
+    public static final ValueModel EMPTY = new ValueModel() {
+        @Override
+        public Class getType() {
+            return Object.class;
+        }
+
+        @Override
+        public Object get() {
+            return null;
+        }
+
+        @Override
+        public void set(Object value) {
+
+        }
+    };
+
+    protected ValueModel() {
+    }
+
+    /**
+     * Returns the type of this property.
+     *
+     * @return the property type
+     */
+    public abstract Class<T> getType();
+
+    /**
+     * Returns the value of this property.
+     *
+     * @return the property value
+     */
+    public abstract T get();
+
+    /**
+     * Sets the value of this property.
+     *
+     * @param value the new value for this property
+     */
+    public abstract void set(T value);
+}
\ No newline at end of file
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 0aabc44..fbda474 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,6 +18,7 @@
 
 import static android.view.accessibility.AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS;
 
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -64,6 +65,8 @@
 
     private final ArrayList<View> mTempArrayList = new ArrayList<View>();
 
+    private final Rect mTempRect = new Rect();
+
     public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
         Looper looper =  viewRootImpl.mHandler.getLooper();
         mMyLooperThreadId = looper.getThread().getId();
@@ -138,7 +141,7 @@
     }
 
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
-            long accessibilityNodeId, int windowLeft, int windowTop, int interactionId,
+            long accessibilityNodeId, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid) {
         Message message = mHandler.obtainMessage();
@@ -150,12 +153,6 @@
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
         args.arg1 = callback;
-
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -180,11 +177,6 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
         mPool.release(args);
 
         List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
@@ -207,6 +199,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(infos);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
                 infos.clear();
             } catch (RemoteException re) {
@@ -216,9 +209,8 @@
     }
 
     public void findAccessibilityNodeInfoByViewIdClientThread(long accessibilityNodeId,
-            int viewId, int windowLeft, int windowTop, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-            long interrogatingTid) {
+            int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+            int flags, int interrogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
         message.arg1 = flags;
@@ -229,11 +221,6 @@
         args.argi2 = interactionId;
         args.arg1 = callback;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -258,11 +245,6 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
         mPool.release(args);
 
         AccessibilityNodeInfo info = null;
@@ -287,6 +269,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(info);
                 callback.setFindAccessibilityNodeInfoResult(info, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -295,25 +278,19 @@
     }
 
     public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId,
-            String text, int windowLeft, int windowTop, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags,
-            int interrogatingPid, long interrogatingTid) {
+            String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+            int flags, int interrogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
         message.arg1 = flags;
 
         SomeArgs args = mPool.acquire();
         args.arg1 = text;
+        args.arg2 = callback;
         args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.arg1 = callback;
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -333,17 +310,11 @@
 
         SomeArgs args = (SomeArgs) message.obj;
         final String text = (String) args.arg1;
+        final IAccessibilityInteractionConnectionCallback callback =
+            (IAccessibilityInteractionConnectionCallback) args.arg2;
         final int accessibilityViewId = args.argi1;
         final int virtualDescendantId = args.argi2;
         final int interactionId = args.argi3;
-
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        final IAccessibilityInteractionConnectionCallback callback =
-            (IAccessibilityInteractionConnectionCallback) moreArgs.arg1;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
         mPool.release(args);
 
         List<AccessibilityNodeInfo> infos = null;
@@ -396,6 +367,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(infos);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -403,9 +375,9 @@
         }
     }
 
-    public void findFocusClientThread(long accessibilityNodeId, int focusType, int windowLeft,
-            int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interogatingPid, long interrogatingTid) {
+    public void findFocusClientThread(long accessibilityNodeId, int focusType, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_FOCUS;
         message.arg1 = flags;
@@ -417,11 +389,6 @@
         args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.arg1 = callback;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -447,11 +414,6 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
         mPool.release(args);
 
         AccessibilityNodeInfo focused = null;
@@ -502,6 +464,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(focused);
                 callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -509,9 +472,9 @@
         }
     }
 
-    public void focusSearchClientThread(long accessibilityNodeId, int direction, int windowLeft,
-            int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interogatingPid, long interrogatingTid) {
+    public void focusSearchClientThread(long accessibilityNodeId, int direction, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FOCUS_SEARCH;
         message.arg1 = flags;
@@ -523,11 +486,6 @@
         args.argi3 = interactionId;
         args.arg1 = callback;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -553,11 +511,6 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
         mPool.release(args);
 
         AccessibilityNodeInfo next = null;
@@ -574,43 +527,15 @@
                 root = mViewRootImpl.mView;
             }
             if (root != null && isShown(root)) {
-                if ((direction & View.FOCUS_ACCESSIBILITY) ==  View.FOCUS_ACCESSIBILITY) {
-                    AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
-                    if (provider != null) {
-                        next = provider.accessibilityFocusSearch(direction, virtualDescendantId);
-                        if (next != null) {
-                            return;
-                        }
-                    }
-                    View nextView = root.focusSearch(direction);
-                    while (nextView != null) {
-                        // If the focus search reached a node with a provider
-                        // we delegate to the provider to find the next one.
-                        // If the provider does not return a virtual view to
-                        // take accessibility focus we try the next view found
-                        // by the focus search algorithm.
-                        provider = nextView.getAccessibilityNodeProvider();
-                        if (provider != null) {
-                            next = provider.accessibilityFocusSearch(direction, View.NO_ID);
-                            if (next != null) {
-                                break;
-                            }
-                            nextView = nextView.focusSearch(direction);
-                        } else {
-                            next = nextView.createAccessibilityNodeInfo();
-                            break;
-                        }
-                    }
-                } else {
-                    View nextView = root.focusSearch(direction);
-                    if (nextView != null) {
-                        next = nextView.createAccessibilityNodeInfo();
-                    }
+                View nextView = root.focusSearch(direction);
+                if (nextView != null) {
+                    next = nextView.createAccessibilityNodeInfo();
                 }
             }
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(next);
                 callback.setFindAccessibilityNodeInfoResult(next, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -706,6 +631,39 @@
         return foundView;
     }
 
+    private void applyApplicationScaleIfNeeded(List<AccessibilityNodeInfo> infos) {
+        if (infos == null) {
+            return;
+        }
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (applicationScale != 1.0f) {
+            final int infoCount = infos.size();
+            for (int i = 0; i < infoCount; i++) {
+                AccessibilityNodeInfo info = infos.get(i);
+                applyApplicationScaleIfNeeded(info);
+            }
+        }
+    }
+
+    private void applyApplicationScaleIfNeeded(AccessibilityNodeInfo info) {
+        if (info == null) {
+            return;
+        }
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (applicationScale != 1.0f) {
+            Rect bounds = mTempRect;
+
+            info.getBoundsInParent(bounds);
+            bounds.scale(applicationScale);
+            info.setBoundsInParent(bounds);
+
+            info.getBoundsInScreen(bounds);
+            bounds.scale(applicationScale);
+            info.setBoundsInScreen(bounds);
+        }
+    }
+
+
     /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
      * querying window content. It is responsible to prefetch a batch of
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 78dc86f..6288ce5 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -164,8 +164,9 @@
         mHandler = new FrameHandler(looper);
         mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
         mLastFrameTimeNanos = Long.MIN_VALUE;
-        mFrameIntervalNanos = (long)(1000000000 /
-                new Display(Display.DEFAULT_DISPLAY, null).getRefreshRate());
+
+        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        mFrameIntervalNanos = (long)(1000000000 / d.getRefreshRate());
 
         mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
         for (int i = 0; i <= CALLBACK_LAST; i++) {
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index c947312..ce49268 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -450,13 +450,5 @@
     private static final Object sStaticInit = new Object();
     private static boolean sInitialized = false;
     private static IWindowManager sWindowManager;
-
-    /**
-     * Returns a display object which uses the metric's width/height instead.
-     * @hide
-     */
-    public static Display createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat) {
-        return new Display(displayId, compat);
-    }
 }
 
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 31a9f05..351c5c3 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -79,17 +79,9 @@
     }
 
     private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
-        if ((direction & View.FOCUS_ACCESSIBILITY) != View.FOCUS_ACCESSIBILITY) {
-            return findNextInputFocus(root, focused, focusedRect, direction);
-        } else {
-            return findNextAccessibilityFocus(root, focused, focusedRect, direction);
-        }
-    }
-
-    private View findNextInputFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
         View next = null;
         if (focused != null) {
-            next = findNextUserSpecifiedInputFocus(root, focused, direction);
+            next = findNextUserSpecifiedFocus(root, focused, direction);
         }
         if (next != null) {
             return next;
@@ -107,7 +99,7 @@
         return next;
     }
 
-    private View findNextUserSpecifiedInputFocus(ViewGroup root, View focused, int direction) {
+    private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
         // check for user specified next focus
         View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
         if (userSetNextFocus != null && userSetNextFocus.isFocusable()
@@ -120,7 +112,6 @@
 
     private View findNextFocus(ViewGroup root, View focused, Rect focusedRect,
             int direction, ArrayList<View> focusables) {
-        final int directionMasked = (direction & ~View.FOCUS_ACCESSIBILITY);
         if (focused != null) {
             if (focusedRect == null) {
                 focusedRect = mFocusedRect;
@@ -132,7 +123,7 @@
             if (focusedRect == null) {
                 focusedRect = mFocusedRect;
                 // make up a rect at top left or bottom right of root
-                switch (directionMasked) {
+                switch (direction) {
                     case View.FOCUS_RIGHT:
                     case View.FOCUS_DOWN:
                         setFocusTopLeft(root, focusedRect);
@@ -160,37 +151,23 @@
             }
         }
 
-        switch (directionMasked) {
+        switch (direction) {
             case View.FOCUS_FORWARD:
             case View.FOCUS_BACKWARD:
-                return findNextInputFocusInRelativeDirection(focusables, root, focused, focusedRect,
-                        directionMasked);
+                return findNextFocusInRelativeDirection(focusables, root, focused, focusedRect,
+                        direction);
             case View.FOCUS_UP:
             case View.FOCUS_DOWN:
             case View.FOCUS_LEFT:
             case View.FOCUS_RIGHT:
-                return findNextInputFocusInAbsoluteDirection(focusables, root, focused,
-                        focusedRect, directionMasked);
+                return findNextFocusInAbsoluteDirection(focusables, root, focused,
+                        focusedRect, direction);
             default:
-                throw new IllegalArgumentException("Unknown direction: " + directionMasked);
+                throw new IllegalArgumentException("Unknown direction: " + direction);
         }
     }
 
-    private View findNextAccessibilityFocus(ViewGroup root, View focused,
-            Rect focusedRect, int direction) {
-        ArrayList<View> focusables = mTempList;
-        try {
-            focusables.clear();
-            root.addFocusables(focusables, direction, View.FOCUSABLES_ACCESSIBILITY);
-            View next = findNextFocus(root, focused, focusedRect, direction,
-                    focusables);
-            return next;
-        } finally {
-            focusables.clear();
-        }
-    }
-
-    private View findNextInputFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
+    private View findNextFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
             View focused, Rect focusedRect, int direction) {
         try {
             // Note: This sort is stable.
@@ -222,7 +199,7 @@
         focusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
     }
 
-    View findNextInputFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
+    View findNextFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
             Rect focusedRect, int direction) {
         // initialize the best candidate to something impossible
         // (so the first plausible view will become the best choice)
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 055aee3..f4ab133 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -151,12 +151,12 @@
     static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
     static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
     static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
+    static native void nSetOpaqueLayer(int layerId, boolean isOpaque);
     static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
             SurfaceTexture surface);
     static native void nSetTextureLayerTransform(int layerId, int matrix);
     static native void nDestroyLayer(int layerId);
     static native void nDestroyLayerDeferred(int layerId);
-    static native void nFlushLayer(int layerId);
     static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
             int left, int top, int right, int bottom);
     static native boolean nCopyLayer(int layerId, int bitmap);
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 4f25792..a0ae379 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -46,11 +46,6 @@
     boolean copyInto(Bitmap bitmap) {
         return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap);
     }
-    
-    @Override
-    void update(int width, int height, boolean isOpaque) {
-        super.update(width, height, isOpaque);
-    }
 
     @Override
     void destroy() {
@@ -60,13 +55,6 @@
         }
         mLayer = 0;
     }
-    
-    @Override
-    void flush() {
-        if (mLayer != 0) {
-            GLES20Canvas.nFlushLayer(mLayer);
-        }
-    }
 
     static class Finalizer {
         private int mLayerId;
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index c727a36..a77425a 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -71,6 +71,12 @@
     }
 
     @Override
+    void setOpaque(boolean isOpaque) {
+        mOpaque = isOpaque;
+        GLES20Canvas.nSetOpaqueLayer(mLayer, isOpaque);
+    }
+
+    @Override
     HardwareCanvas getCanvas() {
         return mCanvas;
     }
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 16a13cf..e198ef6 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -42,12 +42,6 @@
         }        
     }
 
-    GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
-        this(isOpaque);
-        mSurface = surface;
-        mSurface.attachToGLContext(mTexture);
-    }
-
     @Override
     boolean isValid() {
         return mLayer != 0 && mTexture != 0;
@@ -93,6 +87,11 @@
     }
 
     @Override
+    void setOpaque(boolean isOpaque) {
+        throw new UnsupportedOperationException("Use update(int, int, boolean) instead");
+    }
+
+    @Override
     void setTransform(Matrix matrix) {
         GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance);
     }
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index 4547aa6..f031fe7 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -155,7 +155,6 @@
      *
      * @see {@link View#LAYOUT_DIRECTION_LTR}
      * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public static void apply(int gravity, int w, int h, Rect container,
             Rect outRect, int layoutDirection) {
@@ -293,7 +292,6 @@
      *
      * @see {@link View#LAYOUT_DIRECTION_LTR}
      * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public static void apply(int gravity, int w, int h, Rect container,
                              int xAdj, int yAdj, Rect outRect, int layoutDirection) {
@@ -374,7 +372,6 @@
      *
      * @see {@link View#LAYOUT_DIRECTION_LTR}
      * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public static void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {
         int absGravity = getAbsoluteGravity(gravity, layoutDirection);
@@ -411,7 +408,6 @@
      * @param gravity The gravity to convert to absolute (horizontal) values.
      * @param layoutDirection The layout direction.
      * @return gravity converted to absolute (horizontal) values.
-     * @hide
      */
     public static int getAbsoluteGravity(int gravity, int layoutDirection) {
         int result = gravity;
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index e73f7bf..06c6e7c 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -107,6 +107,13 @@
     }
 
     /**
+     * Sets whether or not this layer should be considered opaque.
+     * 
+     * @param isOpaque True if the layer is opaque, false otherwise
+     */
+    abstract void setOpaque(boolean isOpaque);
+
+    /**
      * Indicates whether this layer can be rendered.
      * 
      * @return True if the layer can be rendered into, false otherwise
@@ -136,11 +143,6 @@
     abstract void destroy();
 
     /**
-     * Flush the render queue associated with this layer.
-     */
-    abstract void flush();
-
-    /**
      * This must be invoked before drawing onto this layer.
      * @param currentCanvas
      */
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index dab48b1..8236cd7 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -197,18 +197,18 @@
     /**
      * Initializes the hardware renderer for the specified surface.
      * 
-     * @param holder The holder for the surface to hardware accelerate.
+     * @param surface The surface to hardware accelerate
      * 
      * @return True if the initialization was successful, false otherwise.
      */
-    abstract boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException;
+    abstract boolean initialize(Surface surface) throws Surface.OutOfResourcesException;
     
     /**
      * Updates the hardware renderer for the specified surface.
-     * 
-     * @param holder The holder for the surface to hardware accelerate
+     *
+     * @param surface The surface to hardware accelerate
      */
-    abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
+    abstract void updateSurface(Surface surface) throws Surface.OutOfResourcesException;
 
     /**
      * Destroys the layers used by the specified view hierarchy.
@@ -228,10 +228,10 @@
     /**
      * This method should be invoked whenever the current hardware renderer
      * context should be reset.
-     * 
-     * @param holder The holder for the surface to hardware accelerate
+     *
+     * @param surface The surface to hardware accelerate
      */
-    abstract void invalidate(SurfaceHolder holder);
+    abstract void invalidate(Surface surface);
 
     /**
      * This method should be invoked to ensure the hardware renderer is in
@@ -474,14 +474,14 @@
      *
      * @param width The width of the drawing surface.
      * @param height The height of the drawing surface.
-     * @param holder The target surface
+     * @param surface The surface to hardware accelerate
      */
-    void initializeIfNeeded(int width, int height, SurfaceHolder holder)
+    void initializeIfNeeded(int width, int height, Surface surface)
             throws Surface.OutOfResourcesException {
         if (isRequested()) {
             // We lost the gl context, so recreate it.
             if (!isEnabled()) {
-                if (initialize(holder)) {
+                if (initialize(surface)) {
                     setup(width, height);
                 }
             }
@@ -742,10 +742,10 @@
         }
 
         @Override
-        boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        boolean initialize(Surface surface) throws Surface.OutOfResourcesException {
             if (isRequested() && !isEnabled()) {
                 initializeEgl();
-                mGl = createEglSurface(holder);
+                mGl = createEglSurface(surface);
                 mDestroyed = false;
 
                 if (mGl != null) {
@@ -771,9 +771,9 @@
         }
         
         @Override
-        void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        void updateSurface(Surface surface) throws Surface.OutOfResourcesException {
             if (isRequested() && isEnabled()) {
-                createEglSurface(holder);
+                createEglSurface(surface);
             }
         }
 
@@ -888,7 +888,7 @@
             Log.d(LOG_TAG, "  SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
         }
 
-        GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        GL createEglSurface(Surface surface) throws Surface.OutOfResourcesException {
             // Check preconditions.
             if (sEgl == null) {
                 throw new RuntimeException("egl not initialized");
@@ -908,7 +908,7 @@
             destroySurface();
 
             // Create an EGL surface we can render into.
-            if (!createSurface(holder)) {
+            if (!createSurface(surface)) {
                 return null;
             }
 
@@ -982,7 +982,7 @@
         }
 
         @Override
-        void invalidate(SurfaceHolder holder) {
+        void invalidate(Surface surface) {
             // Cancels any existing buffer to ensure we'll get a buffer
             // of the right size before we call eglSwapBuffers
             sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -993,8 +993,8 @@
                 setEnabled(false);
             }
 
-            if (holder.getSurface().isValid()) {
-                if (!createSurface(holder)) {
+            if (surface.isValid()) {
+                if (!createSurface(surface)) {
                     return;
                 }
 
@@ -1006,8 +1006,8 @@
             }
         }
 
-        private boolean createSurface(SurfaceHolder holder) {
-            mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null);
+        private boolean createSurface(Surface surface) {
+            mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, surface, null);
 
             if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
                 int error = sEgl.eglGetError();
diff --git a/core/java/android/view/IInputFilter.aidl b/core/java/android/view/IInputFilter.aidl
new file mode 100644
index 0000000..fead5f6
--- /dev/null
+++ b/core/java/android/view/IInputFilter.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.view.IInputFilterHost;
+import android.view.InputEvent;
+
+/**
+ * Interface for implementing an filter which observes and
+ * potentially transforms the input event stream in the system.
+ *
+ * @hide
+ */
+oneway interface IInputFilter {
+    void install(IInputFilterHost host);
+    void uninstall();
+    void filterInputEvent(in InputEvent event, int policyFlags);
+}
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/core/java/android/view/IInputFilterHost.aidl
similarity index 64%
rename from packages/SystemUI/res/values-sw720dp-port/dimens.xml
rename to core/java/android/view/IInputFilterHost.aidl
index 74b266d..93b8239 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/core/java/android/view/IInputFilterHost.aidl
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, The Android Open Source Project
+/**
+ * Copyright (c) 2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,10 +12,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
-*/
--->
-<resources>
-    <!-- gap on either side of status bar notification icons -->
-    <dimen name="status_bar_icon_padding">2dp</dimen>
-</resources>
+ */
 
+package android.view;
+
+import android.view.InputEvent;
+
+/**
+ * Interface for calls from an input filter to its host.
+ *
+ * @hide
+ */
+oneway interface IInputFilterHost {
+    void sendInputEvent(in InputEvent event, int policyFlags);
+}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index b4caad3..9f22870 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -47,6 +47,7 @@
 
     void resized(int w, int h, in Rect contentInsets,
             in Rect visibleInsets, boolean reportDraw, in Configuration newConfig);
+    void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
     void dispatchScreenState(boolean on);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 4d4eec7..5941e44 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -23,6 +23,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.IRemoteCallback;
 import android.view.IApplicationToken;
 import android.view.IOnKeyguardExitResult;
@@ -33,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.InputChannel;
 import android.view.InputDevice;
+import  android.view.IInputFilter;
 
 /**
  * System private interface to the window manager.
@@ -208,4 +210,24 @@
      * Lock the device immediately.
      */
     void lockNow();
+
+    /**
+     * Gets the token for the focused window.
+     */
+    IBinder getFocusedWindowToken();
+
+    /**
+     * Gets the frame on the screen of the window given its token.
+     */
+    boolean getWindowFrame(IBinder token, out Rect outBounds);
+
+    /**
+     * Gets the compatibility scale of e window given its token.
+     */
+    float getWindowCompatibilityScale(IBinder windowToken);
+
+    /**
+     * Sets an input filter for manipulating the input event stream.
+     */
+    void setInputFilter(in IInputFilter filter);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d4a03ce..0dc14d5 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -172,4 +172,7 @@
             int z, in Bundle extras, boolean sync);
     
     void wallpaperCommandComplete(IBinder window, in Bundle result);
+
+    void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
+            float dsdx, float dtdx, float dsdy, float dtdy);
 }
diff --git a/services/java/com/android/server/input/InputFilter.java b/core/java/android/view/InputFilter.java
similarity index 94%
rename from services/java/com/android/server/input/InputFilter.java
rename to core/java/android/view/InputFilter.java
index 2ce0a02..c25b87b 100644
--- a/services/java/com/android/server/input/InputFilter.java
+++ b/core/java/android/view/InputFilter.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.server.input;
-
-import com.android.server.wm.WindowManagerService;
+package android.view;
 
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
+import android.view.IInputFilter;
 import android.view.InputEvent;
 import android.view.InputEventConsistencyVerifier;
 import android.view.KeyEvent;
@@ -94,15 +94,14 @@
  * It may be prudent to disable automatic key repeating for synthetic key events
  * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
  * </p>
+ *
+ * @hide
  */
-public abstract class InputFilter {
+public abstract class InputFilter extends IInputFilter.Stub {
     private static final int MSG_INSTALL = 1;
     private static final int MSG_UNINSTALL = 2;
     private static final int MSG_INPUT_EVENT = 3;
 
-    private final H mH;
-    private Host mHost;
-
     // Consistency verifiers for debugging purposes.
     private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
@@ -115,6 +114,10 @@
                             InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
                             "InputFilter#OutboundInputEventConsistencyVerifier") : null;
 
+    private final H mH;
+
+    private IInputFilterHost mHost;
+
     /**
      * Creates the input filter.
      *
@@ -130,7 +133,7 @@
      *
      * @param host The input filter host environment.
      */
-    final void install(Host host) {
+    public final void install(IInputFilterHost host) {
         mH.obtainMessage(MSG_INSTALL, host).sendToTarget();
     }
 
@@ -138,7 +141,7 @@
      * Called when the input filter is uninstalled.
      * This method is guaranteed to be non-reentrant.
      */
-    final void uninstall() {
+    public final void uninstall() {
         mH.obtainMessage(MSG_UNINSTALL).sendToTarget();
     }
 
@@ -149,7 +152,7 @@
      *
      * @param event The input event to enqueue.
      */
-    final void filterInputEvent(InputEvent event, int policyFlags) {
+    final public void filterInputEvent(InputEvent event, int policyFlags) {
         mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
     }
 
@@ -170,7 +173,11 @@
         if (mOutboundInputEventConsistencyVerifier != null) {
             mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0);
         }
-        mHost.sendInputEvent(event, policyFlags);
+        try {
+            mHost.sendInputEvent(event, policyFlags);
+        } catch (RemoteException re) {
+            /* ignore */
+        }
     }
 
     /**
@@ -218,7 +225,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_INSTALL:
-                    mHost = (Host)msg.obj;
+                    mHost = (IInputFilterHost) msg.obj;
                     if (mInboundInputEventConsistencyVerifier != null) {
                         mInboundInputEventConsistencyVerifier.reset();
                     }
@@ -251,8 +258,4 @@
             }
         }
     }
-
-    interface Host {
-        public void sendInputEvent(InputEvent event, int policyFlags);
-    }
 }
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 26a5b26..f692e05 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,6 +20,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.widget.FrameLayout;
+import com.android.internal.R;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -43,20 +44,20 @@
  *
  * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
  *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
- * 
+ *
  * <p>
  * To create a new LayoutInflater with an additional {@link Factory} for your
  * own views, you can use {@link #cloneInContext} to clone an existing
  * ViewFactory, and then call {@link #setFactory} on it to include your
  * Factory.
- * 
+ *
  * <p>
  * For performance reasons, view inflation relies heavily on pre-processing of
  * XML files that is done at build time. Therefore, it is not currently possible
  * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
  * it only works with an XmlPullParser returned from a compiled resource
  * (R.<em>something</em> file.)
- * 
+ *
  * @see Context#getSystemService
  */
 public abstract class LayoutInflater {
@@ -82,7 +83,7 @@
 
     private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
             new HashMap<String, Constructor<? extends View>>();
-    
+
     private HashMap<String, Boolean> mFilterMap;
 
     private static final String TAG_MERGE = "merge";
@@ -93,36 +94,36 @@
     /**
      * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
      * to be inflated.
-     * 
+     *
      */
     public interface Filter {
         /**
          * Hook to allow clients of the LayoutInflater to restrict the set of Views 
          * that are allowed to be inflated.
-         * 
+         *
          * @param clazz The class object for the View that is about to be inflated
-         * 
+         *
          * @return True if this class is allowed to be inflated, or false otherwise
          */
         @SuppressWarnings("unchecked")
         boolean onLoadClass(Class clazz);
     }
-    
+
     public interface Factory {
         /**
          * Hook you can supply that is called when inflating from a LayoutInflater.
          * You can use this to customize the tag names available in your XML
          * layout files.
-         * 
+         *
          * <p>
          * Note that it is good practice to prefix these custom names with your
          * package (i.e., com.coolcompany.apps) to avoid conflicts with system
          * names.
-         * 
+         *
          * @param name Tag name to be inflated.
          * @param context The context the view is being created in.
          * @param attrs Inflation attributes as specified in XML file.
-         * 
+         *
          * @return View Newly created view. Return null for the default
          *         behavior.
          */
@@ -150,14 +151,14 @@
     private static class FactoryMerger implements Factory2 {
         private final Factory mF1, mF2;
         private final Factory2 mF12, mF22;
-        
+
         FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
             mF1 = f1;
             mF2 = f2;
             mF12 = f12;
             mF22 = f22;
         }
-        
+
         public View onCreateView(String name, Context context, AttributeSet attrs) {
             View v = mF1.onCreateView(name, context, attrs);
             if (v != null) return v;
@@ -172,13 +173,13 @@
                     : mF2.onCreateView(name, context, attrs);
         }
     }
-    
+
     /**
      * Create a new LayoutInflater instance associated with a particular Context.
      * Applications will almost always want to use
      * {@link Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
-     * 
+     *
      * @param context The Context in which this LayoutInflater will create its
      * Views; most importantly, this supplies the theme from which the default
      * values for their attributes are retrieved.
@@ -191,7 +192,7 @@
      * Create a new LayoutInflater instance that is a copy of an existing
      * LayoutInflater, optionally with its Context changed.  For use in
      * implementing {@link #cloneInContext}.
-     * 
+     *
      * @param original The original LayoutInflater to copy.
      * @param newContext The new Context to use.
      */
@@ -202,7 +203,7 @@
         mPrivateFactory = original.mPrivateFactory;
         mFilter = original.mFilter;
     }
-    
+
     /**
      * Obtains the LayoutInflater from the given context.
      */
@@ -220,15 +221,15 @@
      * pointing to a different Context than the original.  This is used by
      * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
      * with the new Context theme.
-     * 
+     *
      * @param newContext The new Context to associate with the new LayoutInflater.
      * May be the same as the original Context if desired.
-     * 
+     *
      * @return Returns a brand spanking new LayoutInflater object associated with
      * the given Context.
      */
     public abstract LayoutInflater cloneInContext(Context newContext);
-    
+
     /**
      * Return the context we are running in, for access to resources, class
      * loader, etc.
@@ -264,7 +265,7 @@
      * called on each element name as the xml is parsed. If the factory returns
      * a View, that is added to the hierarchy. If it returns null, the next
      * factory default {@link #onCreateView} method is called.
-     * 
+     *
      * <p>If you have an existing
      * LayoutInflater and want to add your own factory to it, use
      * {@link #cloneInContext} to clone the existing instance and then you
@@ -320,13 +321,13 @@
     public Filter getFilter() {
         return mFilter;
     }
-    
+
     /**
      * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
      * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
      * throw an {@link InflateException}. This filter will replace any previous filter set on this
      * LayoutInflater.
-     * 
+     *
      * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
      *        This filter will replace any previous filter set on this LayoutInflater.
      */
@@ -340,7 +341,7 @@
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param resource ID for an XML layout resource to load (e.g.,
      *        <code>R.layout.main_page</code>)
      * @param root Optional view to be the parent of the generated hierarchy.
@@ -360,7 +361,7 @@
      * reasons, view inflation relies heavily on pre-processing of XML files
      * that is done at build time. Therefore, it is not currently possible to
      * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
-     * 
+     *
      * @param parser XML dom node containing the description of the view
      *        hierarchy.
      * @param root Optional view to be the parent of the generated hierarchy.
@@ -375,7 +376,7 @@
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param resource ID for an XML layout resource to load (e.g.,
      *        <code>R.layout.main_page</code>)
      * @param root Optional view to be the parent of the generated hierarchy (if
@@ -407,7 +408,7 @@
      * reasons, view inflation relies heavily on pre-processing of XML files
      * that is done at build time. Therefore, it is not currently possible to
      * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
-     * 
+     *
      * @param parser XML dom node containing the description of the view
      *        hierarchy.
      * @param root Optional view to be the parent of the generated hierarchy (if
@@ -442,7 +443,7 @@
                 }
 
                 final String name = parser.getName();
-                
+
                 if (DEBUG) {
                     System.out.println("**************************");
                     System.out.println("Creating root view: "
@@ -528,17 +529,17 @@
      * Low-level function for instantiating a view by name. This attempts to
      * instantiate a view class of the given <var>name</var> found in this
      * LayoutInflater's ClassLoader.
-     * 
+     *
      * <p>
      * There are two things that can happen in an error case: either the
      * exception describing the error will be thrown, or a null will be
      * returned. You must deal with both possibilities -- the former will happen
      * the first time createView() is called for a class of a particular name,
      * the latter every time there-after for that class name.
-     * 
+     *
      * @param name The full name of the class to be instantiated.
      * @param attrs The XML attributes supplied for this instance.
-     * 
+     *
      * @return View The newly instantiated view, or null.
      */
     public final View createView(String name, String prefix, AttributeSet attrs)
@@ -551,7 +552,7 @@
                 // Class not found in the cache, see if it's real, and try to add it
                 clazz = mContext.getClassLoader().loadClass(
                         prefix != null ? (prefix + name) : name).asSubclass(View.class);
-                
+
                 if (mFilter != null && clazz != null) {
                     boolean allowed = mFilter.onLoadClass(clazz);
                     if (!allowed) {
@@ -569,7 +570,7 @@
                         // New class -- remember whether it is allowed
                         clazz = mContext.getClassLoader().loadClass(
                                 prefix != null ? (prefix + name) : name).asSubclass(View.class);
-                        
+
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                         mFilterMap.put(name, allowed);
                         if (!allowed) {
@@ -632,10 +633,10 @@
      * given the xml element name. Override it to handle custom view objects. If
      * you override this in your subclass be sure to call through to
      * super.onCreateView(name) for names you do not recognize.
-     * 
+     *
      * @param name The fully qualified class name of the View to be create.
      * @param attrs An AttributeSet of attributes to apply to the View.
-     * 
+     *
      * @return View The View created.
      */
     protected View onCreateView(String name, AttributeSet attrs)
@@ -679,7 +680,7 @@
             if (view == null && mPrivateFactory != null) {
                 view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
             }
-            
+
             if (view == null) {
                 if (-1 == name.indexOf('.')) {
                     view = onCreateView(parent, name, attrs);
@@ -726,7 +727,7 @@
             }
 
             final String name = parser.getName();
-            
+
             if (TAG_REQUEST_FOCUS.equals(name)) {
                 parseRequestFocus(parser, parent);
             } else if (TAG_INCLUDE.equals(name)) {
@@ -741,7 +742,7 @@
                 final ViewGroup viewGroup = (ViewGroup) parent;
                 final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                 rInflate(parser, view, attrs, true);
-                viewGroup.addView(view, params);                
+                viewGroup.addView(view, params);
             } else {
                 final View view = createViewFromTag(parent, name, attrs);
                 final ViewGroup viewGroup = (ViewGroup) parent;
@@ -810,21 +811,14 @@
                         // We try to load the layout params set in the <include /> tag. If
                         // they don't exist, we will rely on the layout params set in the
                         // included XML file.
-                        // During a layoutparams generation, a runtime exception is thrown
-                        // if either layout_width or layout_height is missing. We catch
-                        // this exception and set localParams accordingly: true means we
-                        // successfully loaded layout params from the <include /> tag,
-                        // false means we need to rely on the included layout params.
-                        ViewGroup.LayoutParams params = null;
-                        try {
-                            params = group.generateLayoutParams(attrs);
-                        } catch (RuntimeException e) {
-                            params = group.generateLayoutParams(childAttrs);
-                        } finally {
-                            if (params != null) {
-                                view.setLayoutParams(params);
-                            }
-                        }
+                        TypedArray ta = getContext().obtainStyledAttributes(attrs,
+                                                            R.styleable.ViewGroup_Layout);
+                        boolean definesBothWidthAndHeight =
+                                ta.hasValue(R.styleable.ViewGroup_Layout_layout_width) &&
+                                ta.hasValue(R.styleable.ViewGroup_Layout_layout_height);
+                        AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs;
+                        view.setLayoutParams(group.generateLayoutParams(attributes));
+                        ta.recycle();
 
                         // Inflate all children.
                         rInflate(childParser, view, childAttrs, true);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a968768..1105038 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -216,12 +216,6 @@
     
     /** Hide the surface. Equivalent to calling hide(). @hide */
     public static final int SURFACE_HIDDEN    = 0x01;
-    
-    /** Freeze the surface. Equivalent to calling freeze(). @hide */
-    public static final int SURFACE_FROZEN     = 0x02;
-
-    /** Enable dithering when compositing this surface @hide */
-    public static final int SURFACE_DITHER    = 0x04;
 
     // The mSurfaceControl will only be present for Surfaces used by the window
     // server or system processes. When this class is parceled we defer to the
@@ -413,22 +407,6 @@
     /*
      * set display parameters & screenshots
      */
-    
-    /**
-     * Freezes the specified display, No updating of the screen will occur
-     * until unfreezeDisplay() is called. Everything else works as usual though,
-     * in particular transactions.
-     * @param display
-     * @hide
-     */
-    public static native   void freezeDisplay(int display);
-
-    /**
-     * resume updating the specified display.
-     * @param display
-     * @hide
-     */
-    public static native   void unfreezeDisplay(int display);
 
     /**
      * set the orientation of the given display.
@@ -503,12 +481,6 @@
     /** @hide */
     public native   void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
     /** @hide */
-    public native   void freeze();
-    /** @hide */
-    public native   void unfreeze();
-    /** @hide */
-    public native   void setFreezeTint(int tint);
-    /** @hide */
     public native   void setFlags(int flags, int mask);
     /** @hide */
     public native   void setWindowCrop(Rect crop);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index fd302dc..5d51670 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -458,7 +458,7 @@
                 if (mWindow == null) {
                     mWindow = new MyWindow(this);
                     mLayout.type = mWindowType;
-                    mLayout.gravity = Gravity.LEFT|Gravity.TOP;
+                    mLayout.gravity = Gravity.START|Gravity.TOP;
                     mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
                             mVisible ? VISIBLE : GONE, mContentInsets);
                 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f2a80d0..50c3407 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -90,6 +90,7 @@
 import java.util.Arrays;
 import java.util.Locale;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * <p>
@@ -343,9 +344,10 @@
  * Padding can be used to offset the content of the view by a specific amount of
  * pixels. For instance, a left padding of 2 will push the view's content by
  * 2 pixels to the right of the left edge. Padding can be set using the
- * {@link #setPadding(int, int, int, int)} method and queried by calling
- * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, {@link #getPaddingRight()},
- * {@link #getPaddingBottom()}.
+ * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
+ * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
+ * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
+ * {@link #getPaddingEnd()}.
  * </p>
  *
  * <p>
@@ -627,6 +629,8 @@
  * @attr ref android.R.styleable#View_paddingLeft
  * @attr ref android.R.styleable#View_paddingRight
  * @attr ref android.R.styleable#View_paddingTop
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
  * @attr ref android.R.styleable#View_saveEnabled
  * @attr ref android.R.styleable#View_rotation
  * @attr ref android.R.styleable#View_rotationX
@@ -648,6 +652,7 @@
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
+ * @attr ref android.R.styleable#View_textAlignment
  * @attr ref android.R.styleable#View_transformPivotX
  * @attr ref android.R.styleable#View_transformPivotY
  * @attr ref android.R.styleable#View_translationX
@@ -656,7 +661,7 @@
  *
  * @see android.view.ViewGroup
  */
-public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
+public class View implements Drawable.Callback, KeyEvent.Callback,
         AccessibilityEventSource {
     private static final boolean DBG = false;
 
@@ -1003,14 +1008,6 @@
     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
 
     /**
-     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
-     * should add only accessibility focusable Views.
-     *
-     * @hide
-     */
-    public static final int FOCUSABLES_ACCESSIBILITY = 0x00000002;
-
-    /**
      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
      * item.
      */
@@ -1042,58 +1039,6 @@
      */
     public static final int FOCUS_DOWN = 0x00000082;
 
-    // Accessibility focus directions.
-
-    /**
-     * The accessibility focus which is the current user position when
-     * interacting with the accessibility framework.
-     *
-     * @hide
-     */
-    public static final int FOCUS_ACCESSIBILITY =  0x00001000;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus left.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_LEFT = FOCUS_LEFT | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus up.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_UP = FOCUS_UP | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus right.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_RIGHT = FOCUS_RIGHT | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus down.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_DOWN = FOCUS_DOWN | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus forward.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_FORWARD = FOCUS_FORWARD | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus backward.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_BACKWARD = FOCUS_BACKWARD | FOCUS_ACCESSIBILITY;
-
     /**
      * Bits of {@link #getMeasuredWidthAndState()} and
      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
@@ -1801,28 +1746,24 @@
     /**
      * Horizontal layout direction of this view is from Left to Right.
      * Use with {@link #setLayoutDirection}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_LTR = 0;
 
     /**
      * Horizontal layout direction of this view is from Right to Left.
      * Use with {@link #setLayoutDirection}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_RTL = 1;
 
     /**
      * Horizontal layout direction of this view is inherited from its parent.
      * Use with {@link #setLayoutDirection}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_INHERIT = 2;
 
     /**
      * Horizontal layout direction of this view is from deduced from the default language
      * script for the locale. Use with {@link #setLayoutDirection}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_LOCALE = 3;
 
@@ -1887,7 +1828,6 @@
 
     /**
      * Text direction is inherited thru {@link ViewGroup}
-     * @hide
      */
     public static final int TEXT_DIRECTION_INHERIT = 0;
 
@@ -1895,7 +1835,6 @@
      * Text direction is using "first strong algorithm". The first strong directional character
      * determines the paragraph direction. If there is no strong directional character, the
      * paragraph direction is the view's resolved layout direction.
-     * @hide
      */
     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
 
@@ -1903,31 +1842,26 @@
      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
      * If there are neither, the paragraph direction is the view's resolved layout direction.
-     * @hide
      */
     public static final int TEXT_DIRECTION_ANY_RTL = 2;
 
     /**
      * Text direction is forced to LTR.
-     * @hide
      */
     public static final int TEXT_DIRECTION_LTR = 3;
 
     /**
      * Text direction is forced to RTL.
-     * @hide
      */
     public static final int TEXT_DIRECTION_RTL = 4;
 
     /**
      * Text direction is coming from the system Locale.
-     * @hide
      */
     public static final int TEXT_DIRECTION_LOCALE = 5;
 
     /**
      * Default text direction is inherited
-     * @hide
      */
     protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
 
@@ -1985,7 +1919,6 @@
     /*
      * Default text alignment. The text alignment of this View is inherited from its parent.
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_INHERIT = 0;
 
@@ -1994,7 +1927,6 @@
      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
 
@@ -2002,7 +1934,6 @@
      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
 
@@ -2010,7 +1941,6 @@
      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
 
@@ -2018,7 +1948,6 @@
      * Center the paragraph, e.g. ALIGN_CENTER.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_CENTER = 4;
 
@@ -2027,7 +1956,6 @@
      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
 
@@ -2036,13 +1964,11 @@
      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
 
     /**
      * Default text alignment is inherited
-     * @hide
      */
     protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
 
@@ -2150,71 +2076,7 @@
      */
     static final int VIEW_QUICK_REJECTED = 0x10000000;
 
-    // Accessiblity constants for mPrivateFlags2
-
-    /**
-     * Shift for the bits in {@link #mPrivateFlags2} related to the
-     * "accessibilityFocusable" attribute.
-     */
-    static final int ACCESSIBILITY_FOCUSABLE_SHIFT = 29;
-
-    /**
-     * The system determines whether the view can take accessibility focus - default (recommended).
-     * <p>
-     * Such a view is consideted by the focus search if it is:
-     * <ul>
-     * <li>
-     * Important for accessibility and actionable (clickable, long clickable, focusable)
-     * </li>
-     * <li>
-     * Important for accessibility, not actionable (clickable, long clickable, focusable),
-     * and does not have an actionable predecessor.
-     * </li>
-     * </ul>
-     * An accessibility srvice can request putting accessibility focus on such a view.
-     * </p>
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUSABLE_AUTO = 0x00000000;
-
-    /**
-     * The view can take accessibility focus.
-     * <p>
-     * A view that can take accessibility focus is always considered during focus
-     * search and an accessibility service can request putting accessibility focus
-     * on it.
-     * </p>
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUSABLE_YES = 0x00000001;
-
-    /**
-     * The view can not take accessibility focus.
-     * <p>
-     * A view that can not take accessibility focus is never considered during focus
-     * search and an accessibility service can not request putting accessibility focus
-     * on it.
-     * </p>
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUSABLE_NO = 0x00000002;
-
-    /**
-     * The default whether the view is accessiblity focusable.
-     */
-    static final int ACCESSIBILITY_FOCUSABLE_DEFAULT = ACCESSIBILITY_FOCUSABLE_AUTO;
-
-    /**
-     * Mask for obtainig the bits which specifies how to determine
-     * whether a view is accessibility focusable.
-     */
-    static final int ACCESSIBILITY_FOCUSABLE_MASK = (ACCESSIBILITY_FOCUSABLE_AUTO
-        | ACCESSIBILITY_FOCUSABLE_YES | ACCESSIBILITY_FOCUSABLE_NO)
-        << ACCESSIBILITY_FOCUSABLE_SHIFT;
-
+    // There are a couple of flags left in mPrivateFlags2
 
     /* End of masks for mPrivateFlags2 */
 
@@ -2905,13 +2767,6 @@
     protected int mUserPaddingLeft;
 
     /**
-     * Cache if the user padding is relative.
-     *
-     */
-    @ViewDebug.ExportedProperty(category = "padding")
-    boolean mUserPaddingRelative;
-
-    /**
      * Cache the paddingStart set by the user to append to the scrollbar's size.
      *
      */
@@ -2926,6 +2781,11 @@
     int mUserPaddingEnd;
 
     /**
+     * Default undefined padding
+     */
+    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
+
+    /**
      * @hide
      */
     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
@@ -3217,6 +3077,8 @@
      */
     private boolean mSendingHoverAccessibilityEvents;
 
+    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
+
     /**
      * Simple constructor to use when creating a view from code.
      *
@@ -3231,13 +3093,11 @@
         mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
                 (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
                 (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
-                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT) |
-                (ACCESSIBILITY_FOCUSABLE_DEFAULT << ACCESSIBILITY_FOCUSABLE_SHIFT);
+                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
-        mUserPaddingStart = -1;
-        mUserPaddingEnd = -1;
-        mUserPaddingRelative = false;
+        mUserPaddingStart = UNDEFINED_PADDING;
+        mUserPaddingEnd = UNDEFINED_PADDING;
     }
 
     /**
@@ -3303,8 +3163,8 @@
         int topPadding = -1;
         int rightPadding = -1;
         int bottomPadding = -1;
-        int startPadding = -1;
-        int endPadding = -1;
+        int startPadding = UNDEFINED_PADDING;
+        int endPadding = UNDEFINED_PADDING;
 
         int padding = -1;
 
@@ -3351,10 +3211,10 @@
                     bottomPadding = a.getDimensionPixelSize(attr, -1);
                     break;
                 case com.android.internal.R.styleable.View_paddingStart:
-                    startPadding = a.getDimensionPixelSize(attr, -1);
+                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
                     break;
                 case com.android.internal.R.styleable.View_paddingEnd:
-                    endPadding = a.getDimensionPixelSize(attr, -1);
+                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
                     break;
                 case com.android.internal.R.styleable.View_scrollX:
                     x = a.getDimensionPixelOffset(attr, 0);
@@ -3631,16 +3491,14 @@
 
         setOverScrollMode(overScrollMode);
 
-        if (background != null) {
-            setBackground(background);
-        }
-
         // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
         // layout direction). Those cached values will be used later during padding resolution.
         mUserPaddingStart = startPadding;
         mUserPaddingEnd = endPadding;
 
-        updateUserPaddingRelative();
+        if (background != null) {
+            setBackground(background);
+        }
 
         if (padding >= 0) {
             leftPadding = padding;
@@ -3653,7 +3511,7 @@
         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
         // use the default padding or the padding from the background drawable
         // (stored at this point in mPadding*)
-        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
+        internalSetPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
                 topPadding >= 0 ? topPadding : mPaddingTop,
                 rightPadding >= 0 ? rightPadding : mPaddingRight,
                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
@@ -3688,10 +3546,6 @@
         computeOpaqueFlags();
     }
 
-    private void updateUserPaddingRelative() {
-        mUserPaddingRelative = (mUserPaddingStart >= 0 || mUserPaddingEnd >= 0);
-    }
-
     /**
      * Non-public constructor for use in testing
      */
@@ -3881,6 +3735,15 @@
             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
         }
 
+        // Apply layout direction to the new Drawables if needed
+        final int layoutDirection = getResolvedLayoutDirection();
+        if (track != null) {
+            track.setLayoutDirection(layoutDirection);
+        }
+        if (thumb != null) {
+            thumb.setLayoutDirection(layoutDirection);
+        }
+
         // Re-apply user/background padding so that scrollbar(s) get added
         resolvePadding();
     }
@@ -4502,11 +4365,13 @@
      * @param text The announcement text.
      */
     public void announceForAccessibility(CharSequence text) {
-        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
             AccessibilityEvent event = AccessibilityEvent.obtain(
                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
+            onInitializeAccessibilityEvent(event);
             event.getText().add(text);
-            sendAccessibilityEventUnchecked(event);
+            event.setContentDescription(null);
+            mParent.requestSendAccessibilityEvent(this, event);
         }
     }
 
@@ -4826,6 +4691,7 @@
      */
     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         Rect bounds = mAttachInfo.mTmpInvalRect;
+
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
@@ -4866,10 +4732,7 @@
         }
 
         if (!isAccessibilityFocused()) {
-            final int mode = getAccessibilityFocusable();
-            if (mode == ACCESSIBILITY_FOCUSABLE_YES || mode == ACCESSIBILITY_FOCUSABLE_AUTO) {
-                info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
-            }
+            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
         } else {
             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
         }
@@ -4892,30 +4755,6 @@
     }
 
     /**
-     * Returns the delta between the actual and last reported window left.
-     *
-     * @hide
-     */
-    public int getActualAndReportedWindowLeftDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; 
-        }
-        return 0;
-    }
-
-    /**
-     * Returns the delta between the actual and last reported window top.
-     *
-     * @hide
-     */
-    public int getActualAndReportedWindowTopDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowTop - mAttachInfo.mWindowTop;
-        }
-        return 0;
-    }
-
-    /**
      * Computes whether this view is visible to the user. Such a view is
      * attached, visible, all its predecessors are visible, it is not clipped
      * entirely by its predecessors, and has an alpha greater than zero.
@@ -4929,9 +4768,10 @@
     }
 
     /**
-     * Computes whether the given portion of this view is visible to the user. Such a view is
-     * attached, visible, all its predecessors are visible, has an alpha greater than zero, and
-     * the specified portion is not clipped entirely by its predecessors.
+     * Computes whether the given portion of this view is visible to the user.
+     * Such a view is attached, visible, all its predecessors are visible,
+     * has an alpha greater than zero, and the specified portion is not
+     * clipped entirely by its predecessors.
      *
      * @param boundInView the portion of the view to test; coordinates should be relative; may be
      *                    <code>null</code>, and the entire view will be tested in this case.
@@ -4945,22 +4785,26 @@
      * @hide
      */
     protected boolean isVisibleToUser(Rect boundInView) {
-        Rect visibleRect = mAttachInfo.mTmpInvalRect;
-        Point offset = mAttachInfo.mPoint;
-        // The first two checks are made also made by isShown() which
-        // however traverses the tree up to the parent to catch that.
-        // Therefore, we do some fail fast check to minimize the up
-        // tree traversal.
-        boolean isVisible = mAttachInfo != null
-            && mAttachInfo.mWindowVisibility == View.VISIBLE
-            && getAlpha() > 0
-            && isShown()
-            && getGlobalVisibleRect(visibleRect, offset);
+        if (mAttachInfo != null) {
+            Rect visibleRect = mAttachInfo.mTmpInvalRect;
+            Point offset = mAttachInfo.mPoint;
+            // The first two checks are made also made by isShown() which
+            // however traverses the tree up to the parent to catch that.
+            // Therefore, we do some fail fast check to minimize the up
+            // tree traversal.
+            boolean isVisible = mAttachInfo.mWindowVisibility == View.VISIBLE
+                && getAlpha() > 0
+                && isShown()
+                && getGlobalVisibleRect(visibleRect, offset);
             if (isVisible && boundInView != null) {
                 visibleRect.offset(-offset.x, -offset.y);
-                isVisible &= boundInView.intersect(visibleRect);
+                // isVisible is always true here, use a simple assignment
+                isVisible = boundInView.intersect(visibleRect);
             }
             return isVisible;
+        }
+
+        return false;
     }
 
     /**
@@ -5403,14 +5247,13 @@
      * @return Return true if this view applied the insets and it should not
      * continue propagating further down the hierarchy, false otherwise.
      * @see #getFitsSystemWindows()
-     * @see #setFitsSystemWindows()
+     * @see #setFitsSystemWindows(boolean) 
      * @see #setSystemUiVisibility(int)
      */
     protected boolean fitSystemWindows(Rect insets) {
         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
-            mUserPaddingStart = -1;
-            mUserPaddingEnd = -1;
-            mUserPaddingRelative = false;
+            mUserPaddingStart = UNDEFINED_PADDING;
+            mUserPaddingEnd = UNDEFINED_PADDING;
             if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
                     || mAttachInfo == null
                     || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
@@ -5652,9 +5495,7 @@
      *   {@link #LAYOUT_DIRECTION_RTL},
      *   {@link #LAYOUT_DIRECTION_INHERIT} or
      *   {@link #LAYOUT_DIRECTION_LOCALE}.
-     *
      * @attr ref android.R.styleable#View_layoutDirection
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout", mapping = {
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
@@ -5676,7 +5517,6 @@
      *   {@link #LAYOUT_DIRECTION_LOCALE}.
      *
      * @attr ref android.R.styleable#View_layoutDirection
-     * @hide
      */
     @RemotableViewMethod
     public void setLayoutDirection(int layoutDirection) {
@@ -5687,6 +5527,7 @@
             // Set the new layout direction (filtered) and ask for a layout pass
             mPrivateFlags2 |=
                     ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
+            resolvePadding();
             requestLayout();
         }
     }
@@ -5696,14 +5537,13 @@
      *
      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout", mapping = {
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
     })
     public int getResolvedLayoutDirection() {
-        // The layout diretion will be resolved only if needed
+        // The layout direction will be resolved only if needed
         if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
             resolveLayoutDirection();
         }
@@ -5716,7 +5556,6 @@
      * layout attribute and/or the inherited value from the parent
      *
      * @return true if the layout is right-to-left.
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout")
     public boolean isLayoutRtl() {
@@ -6177,12 +6016,6 @@
         if (views == null) {
             return;
         }
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (isAccessibilityFocusable()) {
-                views.add(this);
-                return;
-            }
-        }
         if (!isFocusable()) {
             return;
         }
@@ -6347,29 +6180,6 @@
         }
     }
 
-    private void requestAccessibilityFocusFromHover() {
-        if (includeForAccessibility() && isActionableForAccessibility()) {
-            requestAccessibilityFocus();
-        } else {
-            if (mParent != null) {
-                View nextFocus = mParent.findViewToTakeAccessibilityFocusFromHover(this, this);
-                if (nextFocus != null) {
-                    nextFocus.requestAccessibilityFocus();
-                }
-            }
-        }
-    }
-
-    private boolean canTakeAccessibilityFocusFromHover() {
-        if (includeForAccessibility() && isActionableForAccessibility()) {
-            return true;
-        }
-        if (mParent != null) {
-            return (mParent.findViewToTakeAccessibilityFocusFromHover(this, this) == this);
-        }
-        return false;
-    }
-
     /**
      * Clears accessibility focus without calling any callback methods
      * normally invoked in {@link #clearAccessibilityFocus()}. This method
@@ -6577,7 +6387,8 @@
             case IMPORTANT_FOR_ACCESSIBILITY_NO:
                 return false;
             case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
-                return isActionableForAccessibility() || hasListenersForAccessibility();
+                return isActionableForAccessibility() || hasListenersForAccessibility()
+                        || getAccessibilityNodeProvider() != null;
             default:
                 throw new IllegalArgumentException("Unknow important for accessibility mode: "
                         + mode);
@@ -6585,73 +6396,6 @@
     }
 
     /**
-     * Gets the mode for determining whether this View can take accessibility focus.
-     *
-     * @return The mode for determining whether a View can take accessibility focus.
-     *
-     * @attr ref android.R.styleable#View_accessibilityFocusable
-     *
-     * @see #ACCESSIBILITY_FOCUSABLE_YES
-     * @see #ACCESSIBILITY_FOCUSABLE_NO
-     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
-     *
-     * @hide
-     */
-    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
-            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_AUTO, to = "auto"),
-            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_YES, to = "yes"),
-            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_NO, to = "no")
-        })
-    public int getAccessibilityFocusable() {
-        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK) >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
-    }
-
-    /**
-     * Sets how to determine whether this view can take accessibility focus.
-     *
-     * @param mode How to determine whether this view can take accessibility focus.
-     *
-     * @attr ref android.R.styleable#View_accessibilityFocusable
-     *
-     * @see #ACCESSIBILITY_FOCUSABLE_YES
-     * @see #ACCESSIBILITY_FOCUSABLE_NO
-     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
-     *
-     * @hide
-     */
-    public void setAccessibilityFocusable(int mode) {
-        if (mode != getAccessibilityFocusable()) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSABLE_MASK;
-            mPrivateFlags2 |= (mode << ACCESSIBILITY_FOCUSABLE_SHIFT)
-                    & ACCESSIBILITY_FOCUSABLE_MASK;
-            notifyAccessibilityStateChanged();
-        }
-    }
-
-    /**
-     * Gets whether this view can take accessibility focus.
-     *
-     * @return Whether the view can take accessibility focus.
-     *
-     * @hide
-     */
-    public boolean isAccessibilityFocusable() {
-        final int mode = (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK)
-                >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
-        switch (mode) {
-            case ACCESSIBILITY_FOCUSABLE_YES:
-                return true;
-            case ACCESSIBILITY_FOCUSABLE_NO:
-                return false;
-            case ACCESSIBILITY_FOCUSABLE_AUTO:
-                return canTakeAccessibilityFocusFromHover()
-                        || getAccessibilityNodeProvider() != null;
-            default:
-                throw new IllegalArgumentException("Unknow accessibility focusable mode: " + mode);
-        }
-    }
-
-    /**
      * Gets the parent for accessibility purposes. Note that the parent for
      * accessibility is not necessary the immediate parent. It is the first
      * predecessor that is important for accessibility.
@@ -6696,10 +6440,7 @@
      */
     public boolean includeForAccessibility() {
         if (mAttachInfo != null) {
-            if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility();
-            }
-            return true;
+            return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
         }
         return false;
     }
@@ -6832,10 +6573,7 @@
                 }
             } break;
             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
-                final int mode = getAccessibilityFocusable();
-                if (!isAccessibilityFocused()
-                        && (mode == ACCESSIBILITY_FOCUSABLE_YES
-                                || mode == ACCESSIBILITY_FOCUSABLE_AUTO)) {
+                if (!isAccessibilityFocused()) {
                     return requestAccessibilityFocus();
                 }
             } break;
@@ -10363,8 +10101,7 @@
     @ViewDebug.ExportedProperty(category = "drawing")
     public boolean isOpaque() {
         return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
-                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
-                        >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
+                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
     }
 
     /**
@@ -10923,7 +10660,7 @@
      * @hide
      */
     protected void recomputePadding() {
-        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
     }
 
     /**
@@ -11331,9 +11068,13 @@
                     scrollBar.setParameters(computeVerticalScrollRange(),
                                             computeVerticalScrollOffset(),
                                             computeVerticalScrollExtent(), true);
-                    switch (mVerticalScrollbarPosition) {
+                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
+                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
+                        verticalScrollbarPosition = isLayoutRtl() ?
+                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
+                    }
+                    switch (verticalScrollbarPosition) {
                         default:
-                        case SCROLLBAR_POSITION_DEFAULT:
                         case SCROLLBAR_POSITION_RIGHT:
                             left = scrollX + width - size - (mUserPaddingRight & inside);
                             break;
@@ -11495,7 +11236,6 @@
      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
      * that the parent directionality can and will be resolved before its children.
      * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
-     * @hide
      */
     public void resolveLayoutDirection() {
         // Clear any previous layout direction resolution
@@ -11505,15 +11245,18 @@
             // Set resolved depending on layout direction
             switch (getLayoutDirection()) {
                 case LAYOUT_DIRECTION_INHERIT:
-                    // If this is root view, no need to look at parent's layout dir.
-                    if (canResolveLayoutDirection()) {
-                        ViewGroup viewGroup = ((ViewGroup) mParent);
+                    // We cannot resolve yet. LTR is by default and let the resolution happen again
+                    // later to get the correct resolved value
+                    if (!canResolveLayoutDirection()) return;
 
-                        if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                        }
-                    } else {
-                        // Nothing to do, LTR by default
+                    ViewGroup viewGroup = ((ViewGroup) mParent);
+
+                    // We cannot resolve yet on the parent too. LTR is by default and let the
+                    // resolution happen again later
+                    if (!viewGroup.canResolveLayoutDirection()) return;
+
+                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 case LAYOUT_DIRECTION_RTL:
@@ -11532,22 +11275,18 @@
         // Set to resolved
         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
         onResolvedLayoutDirectionChanged();
-        // Resolve padding
-        resolvePadding();
     }
 
     /**
      * Called when layout direction has been resolved.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedLayoutDirectionChanged() {
     }
 
     /**
      * Resolve padding depending on layout direction.
-     * @hide
      */
     public void resolvePadding() {
         // If the user specified the absolute padding (either with android:padding or
@@ -11560,14 +11299,16 @@
                 // Start user padding override Right user padding. Otherwise, if Right user
                 // padding is not defined, use the default Right padding. If Right user padding
                 // is defined, just use it.
-                if (mUserPaddingStart >= 0) {
+                if (mUserPaddingStart != UNDEFINED_PADDING) {
                     mUserPaddingRight = mUserPaddingStart;
-                } else if (mUserPaddingRight < 0) {
+                }
+                if (mUserPaddingRight == UNDEFINED_PADDING) {
                     mUserPaddingRight = mPaddingRight;
                 }
-                if (mUserPaddingEnd >= 0) {
+                if (mUserPaddingEnd != UNDEFINED_PADDING) {
                     mUserPaddingLeft = mUserPaddingEnd;
-                } else if (mUserPaddingLeft < 0) {
+                }
+                if (mUserPaddingLeft == UNDEFINED_PADDING) {
                     mUserPaddingLeft = mPaddingLeft;
                 }
                 break;
@@ -11576,25 +11317,23 @@
                 // Start user padding override Left user padding. Otherwise, if Left user
                 // padding is not defined, use the default left padding. If Left user padding
                 // is defined, just use it.
-                if (mUserPaddingStart >= 0) {
+                if (mUserPaddingStart != UNDEFINED_PADDING) {
                     mUserPaddingLeft = mUserPaddingStart;
-                } else if (mUserPaddingLeft < 0) {
+                }
+                if (mUserPaddingLeft == UNDEFINED_PADDING) {
                     mUserPaddingLeft = mPaddingLeft;
                 }
-                if (mUserPaddingEnd >= 0) {
+                if (mUserPaddingEnd != UNDEFINED_PADDING) {
                     mUserPaddingRight = mUserPaddingEnd;
-                } else if (mUserPaddingRight < 0) {
+                }
+                if (mUserPaddingRight == UNDEFINED_PADDING) {
                     mUserPaddingRight = mPaddingRight;
                 }
         }
 
         mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
 
-        if(isPaddingRelative()) {
-            setPaddingRelative(mUserPaddingStart, mPaddingTop, mUserPaddingEnd, mUserPaddingBottom);
-        } else {
-            recomputePadding();
-        }
+        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
         onPaddingChanged(resolvedLayoutDirection);
     }
 
@@ -11607,7 +11346,6 @@
      *
      * @see {@link #LAYOUT_DIRECTION_LTR}
      * @see {@link #LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public void onPaddingChanged(int layoutDirection) {
     }
@@ -11616,7 +11354,6 @@
      * Check if layout direction resolution can be done.
      *
      * @return true if layout direction resolution can be done otherwise return false.
-     * @hide
      */
     public boolean canResolveLayoutDirection() {
         switch (getLayoutDirection()) {
@@ -11630,7 +11367,6 @@
     /**
      * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
      * when reset is done.
-     * @hide
      */
     public void resetResolvedLayoutDirection() {
         // Reset the current resolved bits
@@ -11647,7 +11383,6 @@
      * resolved layout direction, or to inform child views that inherit their layout direction.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedLayoutDirectionReset() {
     }
@@ -11657,7 +11392,6 @@
      *
      * @param locale Locale to check
      * @return true if the Locale uses an RTL script.
-     * @hide
      */
     protected static boolean isLayoutDirectionRtl(Locale locale) {
         return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
@@ -12135,13 +11869,6 @@
         }
     }
 
-    // Make sure the HardwareRenderer.validate() was invoked before calling this method
-    void flushLayer() {
-        if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
-            mHardwareLayer.flush();
-        }
-    }
-
     /**
      * <p>Returns a hardware layer that can be used to draw this view again
      * without executing its draw method.</p>
@@ -12168,9 +11895,24 @@
                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
                         width, height, isOpaque());
                 mLocalDirtyRect.set(0, 0, width, height);
-            } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
-                mHardwareLayer.resize(width, height);
-                mLocalDirtyRect.set(0, 0, width, height);
+            } else {
+                if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
+                    mHardwareLayer.resize(width, height);
+                    mLocalDirtyRect.set(0, 0, width, height);
+                }
+
+                // This should not be necessary but applications that change
+                // the parameters of their background drawable without calling
+                // this.setBackground(Drawable) can leave the view in a bad state
+                // (for instance isOpaque() returns true, but the background is
+                // not opaque.)
+                computeOpaqueFlags();
+
+                final boolean opaque = isOpaque();
+                if (mHardwareLayer.isOpaque() != opaque) {
+                    mHardwareLayer.setOpaque(opaque);
+                    mLocalDirtyRect.set(0, 0, width, height);
+                }
             }
 
             // The layer is not valid if the underlying GPU resources cannot be allocated
@@ -12382,9 +12124,7 @@
                 canvas.setViewport(width, height);
                 // The dirty rect should always be null for a display list
                 canvas.onPreDraw(null);
-                int layerType = (
-                        !(mParent instanceof ViewGroup) || ((ViewGroup)mParent).mDrawLayers) ?
-                        getLayerType() : LAYER_TYPE_NONE;
+                int layerType = getLayerType();
                 if (!isLayer && layerType != LAYER_TYPE_NONE) {
                     if (layerType == LAYER_TYPE_HARDWARE) {
                         final HardwareLayer layer = getHardwareLayer();
@@ -12979,10 +12719,10 @@
 
         if (more) {
             if (!a.willChangeBounds()) {
-                if ((flags & (parent.FLAG_OPTIMIZE_INVALIDATE | parent.FLAG_ANIMATION_DONE)) ==
-                        parent.FLAG_OPTIMIZE_INVALIDATE) {
-                    parent.mGroupFlags |= parent.FLAG_INVALIDATE_REQUIRED;
-                } else if ((flags & parent.FLAG_INVALIDATE_REQUIRED) == 0) {
+                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
+                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
+                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
+                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
                     // The child need to draw an animation, potentially offscreen, so
                     // make sure we do not cancel invalidate requests
                     parent.mPrivateFlags |= DRAW_ANIMATION;
@@ -13091,7 +12831,7 @@
 
         boolean scalingRequired = false;
         boolean caching;
-        int layerType = parent.mDrawLayers ? getLayerType() : LAYER_TYPE_NONE;
+        int layerType = getLayerType();
 
         final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
         if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
@@ -13137,7 +12877,8 @@
         // to call invalidate() successfully when doing animations
         mPrivateFlags |= DRAWN;
 
-        if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
+        if (!concatMatrix && (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == 0 &&
+                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
                 (mPrivateFlags & DRAW_ANIMATION) == 0) {
             mPrivateFlags2 |= VIEW_QUICK_REJECTED;
             return more;
@@ -13151,11 +12892,6 @@
             mPrivateFlags &= ~INVALIDATED;
         }
 
-        computeScroll();
-
-        final int sx = mScrollX;
-        final int sy = mScrollY;
-
         DisplayList displayList = null;
         Bitmap cache = null;
         boolean hasDisplayList = false;
@@ -13202,6 +12938,14 @@
             }
         }
 
+        int sx = 0;
+        int sy = 0;
+        if (!hasDisplayList) {
+            computeScroll();
+            sx = mScrollX;
+            sy = mScrollY;
+        }
+
         final boolean hasNoCache = cache == null || hasDisplayList;
         final boolean offsetForScroll = cache == null && !hasDisplayList &&
                 layerType != LAYER_TYPE_HARDWARE;
@@ -13963,13 +13707,29 @@
     }
 
     /**
-    * Return the layout direction of a given Drawable.
-    *
-    * @param who the Drawable to query
-    * @hide
-    */
-    public int getResolvedLayoutDirection(Drawable who) {
-        return (who == mBackground) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
+     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
+     * that the View directionality can and will be resolved before its Drawables.
+     *
+     * Will call {@link View#onResolveDrawables} when resolution is done.
+     */
+    public void resolveDrawables() {
+        if (mBackground != null) {
+            mBackground.setLayoutDirection(getResolvedLayoutDirection());
+        }
+        onResolveDrawables(getResolvedLayoutDirection());
+    }
+
+    /**
+     * Called when layout direction has been resolved.
+     *
+     * The default implementation does nothing.
+     *
+     * @param layoutDirection The resolved layout direction.
+     *
+     * @see {@link #LAYOUT_DIRECTION_LTR}
+     * @see {@link #LAYOUT_DIRECTION_RTL}
+     */
+    public void onResolveDrawables(int layoutDirection) {
     }
 
     /**
@@ -14168,6 +13928,7 @@
     public void setBackgroundColor(int color) {
         if (mBackground instanceof ColorDrawable) {
             ((ColorDrawable) mBackground).setColor(color);
+            computeOpaqueFlags();
         } else {
             setBackground(new ColorDrawable(color));
         }
@@ -14215,6 +13976,8 @@
      */
     @Deprecated
     public void setBackgroundDrawable(Drawable background) {
+        computeOpaqueFlags();
+
         if (background == mBackground) {
             return;
         }
@@ -14238,14 +14001,15 @@
                 padding = new Rect();
                 sThreadLocal.set(padding);
             }
+            background.setLayoutDirection(getResolvedLayoutDirection());
             if (background.getPadding(padding)) {
-                switch (background.getResolvedLayoutDirectionSelf()) {
+                switch (background.getLayoutDirection()) {
                     case LAYOUT_DIRECTION_RTL:
-                        setPadding(padding.right, padding.top, padding.left, padding.bottom);
+                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
                         break;
                     case LAYOUT_DIRECTION_LTR:
                     default:
-                        setPadding(padding.left, padding.top, padding.right, padding.bottom);
+                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
                 }
             }
 
@@ -14335,9 +14099,8 @@
      * @param bottom the bottom padding in pixels
      */
     public void setPadding(int left, int top, int right, int bottom) {
-        mUserPaddingStart = -1;
-        mUserPaddingEnd = -1;
-        mUserPaddingRelative = false;
+        mUserPaddingStart = UNDEFINED_PADDING;
+        mUserPaddingEnd = UNDEFINED_PADDING;
 
         internalSetPadding(left, top, right, bottom);
     }
@@ -14357,7 +14120,7 @@
                         ? 0 : getVerticalScrollbarWidth();
                 switch (mVerticalScrollbarPosition) {
                     case SCROLLBAR_POSITION_DEFAULT:
-                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (isLayoutRtl()) {
                             left += offset;
                         } else {
                             right += offset;
@@ -14402,18 +14165,23 @@
     /**
      * Sets the relative padding. The view may add on the space required to display
      * the scrollbars, depending on the style and visibility of the scrollbars.
+     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
+     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
      * from the values set in this call.
      *
+     * @attr ref android.R.styleable#View_padding
+     * @attr ref android.R.styleable#View_paddingBottom
+     * @attr ref android.R.styleable#View_paddingStart
+     * @attr ref android.R.styleable#View_paddingEnd
+     * @attr ref android.R.styleable#View_paddingTop
      * @param start the start padding in pixels
      * @param top the top padding in pixels
      * @param end the end padding in pixels
      * @param bottom the bottom padding in pixels
-     * @hide
      */
     public void setPaddingRelative(int start, int top, int end, int bottom) {
         mUserPaddingStart = start;
         mUserPaddingEnd = end;
-        mUserPaddingRelative = true;
 
         switch(getResolvedLayoutDirection()) {
             case LAYOUT_DIRECTION_RTL:
@@ -14462,7 +14230,6 @@
      * required to display the scrollbars as well.
      *
      * @return the start padding in pixels
-     * @hide
      */
     public int getPaddingStart() {
         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
@@ -14486,7 +14253,6 @@
      * required to display the scrollbars as well.
      *
      * @return the end padding in pixels
-     * @hide
      */
     public int getPaddingEnd() {
         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
@@ -14495,13 +14261,14 @@
 
     /**
      * Return if the padding as been set thru relative values
-     * {@link #setPaddingRelative(int, int, int, int)}
+     * {@link #setPaddingRelative(int, int, int, int)} or thru
+     * @attr ref android.R.styleable#View_paddingStart or
+     * @attr ref android.R.styleable#View_paddingEnd
      *
      * @return true if the padding is relative or false if it is not.
-     * @hide
      */
     public boolean isPaddingRelative() {
-        return mUserPaddingRelative;
+        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
     }
 
     /**
@@ -16297,7 +16064,6 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -16322,7 +16088,6 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
      */
     public void setTextDirection(int textDirection) {
         if (getTextDirection() != textDirection) {
@@ -16352,7 +16117,6 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
      */
     public int getResolvedTextDirection() {
         // The text direction will be resolved only if needed
@@ -16365,7 +16129,6 @@
     /**
      * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
      * resolution is done.
-     * @hide
      */
     public void resolveTextDirection() {
         // Reset any previous text direction resolution
@@ -16426,7 +16189,6 @@
      * resolution should override this method.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedTextDirectionChanged() {
     }
@@ -16435,7 +16197,6 @@
      * Check if text direction resolution can be done.
      *
      * @return true if text direction resolution can be done otherwise return false.
-     * @hide
      */
     public boolean canResolveTextDirection() {
         switch (getTextDirection()) {
@@ -16450,7 +16211,6 @@
      * Reset resolved text direction. Text direction can be resolved with a call to
      * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
      * reset is done.
-     * @hide
      */
     public void resetResolvedTextDirection() {
         mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
@@ -16461,7 +16221,6 @@
      * Called when text direction is reset. Subclasses that care about text direction reset should
      * override this method and do a reset of the text direction of their children. The default
      * implementation does nothing.
-     * @hide
      */
     public void onResolvedTextDirectionReset() {
     }
@@ -16479,7 +16238,6 @@
      * {@link #TEXT_ALIGNMENT_TEXT_END},
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -16508,7 +16266,6 @@
      * {@link #TEXT_ALIGNMENT_VIEW_END}
      *
      * @attr ref android.R.styleable#View_textAlignment
-     * @hide
      */
     public void setTextAlignment(int textAlignment) {
         if (textAlignment != getTextAlignment()) {
@@ -16538,7 +16295,6 @@
      * {@link #TEXT_ALIGNMENT_TEXT_END},
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -16560,7 +16316,6 @@
     /**
      * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
      * resolution is done.
-     * @hide
      */
     public void resolveTextAlignment() {
         // Reset any previous text alignment resolution
@@ -16625,7 +16380,6 @@
      * Check if text alignment resolution can be done.
      *
      * @return true if text alignment resolution can be done otherwise return false.
-     * @hide
      */
     public boolean canResolveTextAlignment() {
         switch (getTextAlignment()) {
@@ -16641,7 +16395,6 @@
      * resolution should override this method.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedTextAlignmentChanged() {
     }
@@ -16650,7 +16403,6 @@
      * Reset resolved text alignment. Text alignment can be resolved with a call to
      * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
      * reset is done.
-     * @hide
      */
     public void resetResolvedTextAlignment() {
         // Reset any previous text alignment resolution
@@ -16662,11 +16414,28 @@
      * Called when text alignment is reset. Subclasses that care about text alignment reset should
      * override this method and do a reset of the text alignment of their children. The default
      * implementation does nothing.
-     * @hide
      */
     public void onResolvedTextAlignmentReset() {
     }
 
+    /**
+     * Generate a value suitable for use in {@link #setId(int)}.
+     * This value will not collide with ID values generated at build time by aapt for R.id.
+     *
+     * @return a generated ID value
+     */
+    public static int generateViewId() {
+        for (;;) {
+            final int result = sNextGeneratedId.get();
+            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
+            int newValue = result + 1;
+            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
+            if (sNextGeneratedId.compareAndSet(result, newValue)) {
+                return result;
+            }
+        }
+    }
+
     //
     // Properties
     //
@@ -17359,20 +17128,6 @@
         int mWindowTop;
 
         /**
-         * Left actual position of this view's window.
-         *
-         * TODO: This is a workaround for 6623031. Remove when fixed.
-         */
-        int mActualWindowLeft;
-
-        /**
-         * Actual top position of this view's window.
-         *
-         * TODO: This is a workaround for 6623031. Remove when fixed.
-         */
-        int mActualWindowTop;
-
-        /**
          * Indicates whether views need to use 32-bit drawing caches
          */
         boolean mUse32BitDrawingCache;
@@ -17542,6 +17297,16 @@
         final RectF mTmpTransformRect = new RectF();
 
         /**
+         * Temporary for use in transforming invalidation rect
+         */
+        final Matrix mTmpMatrix = new Matrix();
+
+        /**
+         * Temporary for use in transforming invalidation rect
+         */
+        final Transformation mTmpTransformation = new Transformation();
+
+        /**
          * Temporary list for use in collecting focusable descendents of a view.
          */
         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 823befb..107f1cc 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -30,24 +30,6 @@
  */
 public class ViewConfiguration {
     /**
-     * Expected bit depth of the display panel.
-     *
-     * @hide
-     */
-    public static final float PANEL_BIT_DEPTH = 24;
-
-    /**
-     * Minimum alpha required for a view to draw.
-     *
-     * @hide
-     */
-    public static final float ALPHA_THRESHOLD = 0.5f / PANEL_BIT_DEPTH;
-    /**
-     * @hide
-     */
-    public static final float ALPHA_THRESHOLD_INT = 0x7f / PANEL_BIT_DEPTH;
-
-    /**
      * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
      * dips
      */
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index dd671dc..00d4fc7 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -255,6 +255,35 @@
         boolean retrieveReturn() default false;
     }
 
+    /**
+     * Allows a View to inject custom children into HierarchyViewer. For example,
+     * WebView uses this to add its internal layer tree as a child to itself
+     * @hide
+     */
+    public interface HierarchyHandler {
+        /**
+         * Dumps custom children to hierarchy viewer.
+         * See ViewDebug.dumpViewWithProperties(Context, View, BufferedWriter, int)
+         * for the format
+         *
+         * An empty implementation should simply do nothing
+         *
+         * @param out The output writer
+         * @param level The indentation level
+         */
+        public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+        /**
+         * Returns a View to enable grabbing screenshots from custom children
+         * returned in dumpViewHierarchyWithProperties.
+         *
+         * @param className The className of the view to find
+         * @param hashCode The hashCode of the view to find
+         * @return the View to capture from, or null if not found
+         */
+        public View findHierarchyView(String className, int hashCode);
+    }
+
     private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
     private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
 
@@ -759,6 +788,13 @@
             } else if (isRequestedView(view, className, hashCode)) {
                 return view;
             }
+            if (view instanceof HierarchyHandler) {
+                final View found = ((HierarchyHandler)view)
+                        .findHierarchyView(className, hashCode);
+                if (found != null) {
+                    return found;
+                }
+            }
         }
 
         return null;
@@ -783,6 +819,9 @@
                 dumpViewWithProperties(context, view, out, level + 1);
             }
         }
+        if (group instanceof HierarchyHandler) {
+            ((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1);
+        }
     }
 
     private static boolean dumpViewWithProperties(Context context, View view,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0c83a73..95eed33 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -404,10 +404,6 @@
     // views during a transition when they otherwise would have become gone/invisible
     private ArrayList<View> mVisibilityChangingChildren;
 
-    // Indicates whether this container will use its children layers to draw
-    @ViewDebug.ExportedProperty(category = "drawing")
-    boolean mDrawLayers = true;
-
     // Indicates how many of this container's child subtrees contain transient state
     @ViewDebug.ExportedProperty(category = "layout")
     private int mChildCountWithTransientState = 0;
@@ -628,11 +624,7 @@
      *        FOCUS_RIGHT, or 0 for not applicable.
      */
     public View focusSearch(View focused, int direction) {
-        // If we are moving accessibility focus we want to consider all
-        // views no matter if they are on the screen. It is responsibility
-        // of the accessibility service to check whether the result is in
-        // the screen.
-        if (isRootNamespace() && (direction & FOCUS_ACCESSIBILITY) == 0) {
+        if (isRootNamespace()) {
             // root namespace means we should consider ourselves the top of the
             // tree for focus searching; otherwise we could be focus searching
             // into other tabs.  see LocalActivityManager and TabHost for more info
@@ -867,8 +859,7 @@
 
         final int descendantFocusability = getDescendantFocusability();
 
-        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS
-                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
+        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
             final int count = mChildrenCount;
             final View[] children = mChildren;
 
@@ -886,9 +877,7 @@
         // among the focusable children would be more interesting.
         if (descendantFocusability != FOCUS_AFTER_DESCENDANTS
                 // No focusable descendants
-                || (focusableCount == views.size())
-                // We are collecting accessibility focusables.
-                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
+                || (focusableCount == views.size())) {
             super.addFocusables(views, direction, focusableMode);
         }
     }
@@ -1658,20 +1647,6 @@
     }
 
     /**
-     * @hide
-     */
-    @Override
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-        if (includeForAccessibility() && isActionableForAccessibility()) {
-            return this;
-        }
-        if (mParent != null) {
-            return mParent.findViewToTakeAccessibilityFocusFromHover(this, descendant);
-        }
-        return null;
-    }
-
-    /**
      * Implement this method to intercept hover events before they are handled
      * by child views.
      * <p>
@@ -2930,45 +2905,6 @@
     }
 
     /**
-     * 
-     * @param enabled True if children should be drawn with layers, false otherwise.
-     * 
-     * @hide
-     */
-    public void setChildrenLayersEnabled(boolean enabled) {
-        if (enabled != mDrawLayers) {
-            mDrawLayers = enabled;
-            invalidate(true);
-
-            boolean flushLayers = !enabled;
-            AttachInfo info = mAttachInfo;
-            if (info != null && info.mHardwareRenderer != null &&
-                    info.mHardwareRenderer.isEnabled()) {
-                if (!info.mHardwareRenderer.validate()) {
-                    flushLayers = false;
-                }
-            } else {
-                flushLayers = false;
-            }
-
-            // We need to invalidate any child with a layer. For instance,
-            // if a child is backed by a hardware layer and we disable layers
-            // the child is marked as not dirty (flags cleared the last time
-            // the child was drawn inside its layer.) However, that child might
-            // never have created its own display list or have an obsolete
-            // display list. By invalidating the child we ensure the display
-            // list is in sync with the content of the hardware layer.
-            for (int i = 0; i < mChildrenCount; i++) {
-                View child = mChildren[i];
-                if (child.mLayerType != LAYER_TYPE_NONE) {
-                    if (flushLayers) child.flushLayer();
-                    child.invalidate(true);
-                }
-            }
-        }
-    }
-
-    /**
      * By default, children are clipped to their bounds before drawing. This
      * allows view groups to override this behavior for animations, etc.
      *
@@ -3052,7 +2988,7 @@
      *
      * @param enabled True to enable static transformations on children, false otherwise.
      *
-     * @see #FLAG_SUPPORT_STATIC_TRANSFORMATIONS
+     * @see #getChildStaticTransformation(View, android.view.animation.Transformation)
      */
     protected void setStaticTransformationsEnabled(boolean enabled) {
         setBooleanFlag(FLAG_SUPPORT_STATIC_TRANSFORMATIONS, enabled);
@@ -3062,7 +2998,8 @@
      * Sets  <code>t</code> to be the static transformation of the child, if set, returning a
      * boolean to indicate whether a static transform was set. The default implementation
      * simply returns <code>false</code>; subclasses may override this method for different
-     * behavior.
+     * behavior. {@link #setStaticTransformationsEnabled(boolean)} must be set to true
+     * for this method to be called.
      *
      * @param child The child view whose static transform is being requested
      * @param t The Transformation which will hold the result
@@ -4026,11 +3963,27 @@
             final int[] location = attachInfo.mInvalidateChildLocation;
             location[CHILD_LEFT_INDEX] = child.mLeft;
             location[CHILD_TOP_INDEX] = child.mTop;
-            if (!childMatrix.isIdentity()) {
+            if (!childMatrix.isIdentity() ||
+                    (mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
                 RectF boundingRect = attachInfo.mTmpTransformRect;
                 boundingRect.set(dirty);
-                //boundingRect.inset(-0.5f, -0.5f);
-                childMatrix.mapRect(boundingRect);
+                Matrix transformMatrix;
+                if ((mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
+                    Transformation t = attachInfo.mTmpTransformation;
+                    boolean transformed = getChildStaticTransformation(child, t);
+                    if (transformed) {
+                        transformMatrix = attachInfo.mTmpMatrix;
+                        transformMatrix.set(t.getMatrix());
+                        if (!childMatrix.isIdentity()) {
+                            transformMatrix.preConcat(childMatrix);
+                        }
+                    } else {
+                        transformMatrix = childMatrix;
+                    }
+                } else {
+                    transformMatrix = childMatrix;
+                }
+                transformMatrix.mapRect(boundingRect);
                 dirty.set((int) (boundingRect.left - 0.5f),
                         (int) (boundingRect.top - 0.5f),
                         (int) (boundingRect.right + 0.5f),
@@ -5245,9 +5198,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedLayoutDirectionReset() {
         // Take care of resetting the children resolution too
@@ -5260,9 +5210,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedTextDirectionReset() {
         // Take care of resetting the children resolution too
@@ -5275,9 +5222,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedTextAlignmentReset() {
         // Take care of resetting the children resolution too
@@ -5448,15 +5392,19 @@
         }
 
         /**
-         * Extracts the layout parameters from the supplied attributes.
+         * Extracts the <code>width</code> and <code>height</code> layout parameters
+         * from the supplied TypedArray, <code>a</code>, and assigns them
+         * to the appropriate fields. If, <code>a</code>, does not contain an
+         * entry for either attribute, the value, {@link ViewGroup.LayoutParams#WRAP_CONTENT},
+         * is used as a default.
          *
          * @param a the style attributes to extract the parameters from
          * @param widthAttr the identifier of the width attribute
          * @param heightAttr the identifier of the height attribute
          */
         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
-            width = a.getLayoutDimension(widthAttr, "layout_width");
-            height = a.getLayoutDimension(heightAttr, "layout_height");
+            width = a.getLayoutDimension(widthAttr, WRAP_CONTENT);
+            height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
         }
 
         /**
@@ -5468,7 +5416,6 @@
          *
          * {@link View#LAYOUT_DIRECTION_LTR}
          * {@link View#LAYOUT_DIRECTION_RTL}
-         * @hide
          */
         public void onResolveLayoutDirection(int layoutDirection) {
         }
@@ -5560,7 +5507,6 @@
          * The start margin in pixels of the child.
          * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
          * to this field.
-         * @hide
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int startMargin = DEFAULT_RELATIVE;
@@ -5569,15 +5515,23 @@
          * The end margin in pixels of the child.
          * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
          * to this field.
-         * @hide
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int endMargin = DEFAULT_RELATIVE;
 
         /**
          * The default start and end margin.
+         * @hide
          */
-        static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+        public static final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+
+        private int initialLeftMargin;
+        private int initialRightMargin;
+
+        private static int LAYOUT_DIRECTION_UNDEFINED = -1;
+
+        // Layout direction undefined by default
+        private int layoutDirection = LAYOUT_DIRECTION_UNDEFINED;
 
         /**
          * Creates a new set of layout parameters. The values are extracted from
@@ -5617,6 +5571,9 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
+            initialLeftMargin = leftMargin;
+            initialRightMargin = rightMargin;
+
             a.recycle();
         }
 
@@ -5642,6 +5599,11 @@
             this.bottomMargin = source.bottomMargin;
             this.startMargin = source.startMargin;
             this.endMargin = source.endMargin;
+
+            this.initialLeftMargin = source.leftMargin;
+            this.initialRightMargin = source.rightMargin;
+
+            setLayoutDirection(source.layoutDirection);
         }
 
         /**
@@ -5671,6 +5633,8 @@
             topMargin = top;
             rightMargin = right;
             bottomMargin = bottom;
+            initialLeftMargin = left;
+            initialRightMargin = right;
         }
 
         /**
@@ -5688,6 +5652,7 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
+         *
          * @hide
          */
         public void setMarginsRelative(int start, int top, int end, int bottom) {
@@ -5695,6 +5660,8 @@
             topMargin = top;
             endMargin = end;
             bottomMargin = bottom;
+            initialLeftMargin = 0;
+            initialRightMargin = 0;
         }
 
         /**
@@ -5703,10 +5670,16 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
          *
          * @return the start margin in pixels.
-         * @hide
          */
         public int getMarginStart() {
-            return startMargin;
+            if (startMargin != DEFAULT_RELATIVE) return startMargin;
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    return rightMargin;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    return leftMargin;
+            }
         }
 
         /**
@@ -5715,10 +5688,16 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
          *
          * @return the end margin in pixels.
-         * @hide
          */
         public int getMarginEnd() {
-            return endMargin;
+            if (endMargin != DEFAULT_RELATIVE) return endMargin;
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    return leftMargin;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    return rightMargin;
+            }
         }
 
         /**
@@ -5727,33 +5706,61 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
          *
-         * @return true if either marginStart or marginEnd has been set
-         * @hide
+         * @return true if either marginStart or marginEnd has been set.
          */
         public boolean isMarginRelative() {
             return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
         }
 
         /**
+         * Set the layout direction
+         * @param layoutDirection the layout direction.
+         *        Should be either {@link View#LAYOUT_DIRECTION_LTR}
+         *                     or {@link View#LAYOUT_DIRECTION_RTL}.
+         */
+        public void setLayoutDirection(int layoutDirection) {
+            if (layoutDirection != View.LAYOUT_DIRECTION_LTR &&
+                    layoutDirection != View.LAYOUT_DIRECTION_RTL) return;
+            this.layoutDirection = layoutDirection;
+        }
+
+        /**
+         * Retuns the layout direction. Can be either {@link View#LAYOUT_DIRECTION_LTR} or
+         * {@link View#LAYOUT_DIRECTION_RTL}.
+         *
+         * @return the layout direction.
+         */
+        public int getLayoutDirection() {
+            return layoutDirection;
+        }
+
+        /**
          * This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
          * may be overridden depending on layout direction.
-         * @hide
          */
         @Override
         public void onResolveLayoutDirection(int layoutDirection) {
+            setLayoutDirection(layoutDirection);
+
+            if (!isMarginRelative()) return;
+
             switch(layoutDirection) {
                 case View.LAYOUT_DIRECTION_RTL:
-                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
-                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
+                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialLeftMargin;
+                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialRightMargin;
                     break;
                 case View.LAYOUT_DIRECTION_LTR:
                 default:
-                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
-                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
+                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialLeftMargin;
+                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialRightMargin;
                     break;
             }
         }
 
+        protected boolean isLayoutRtl() {
+            return (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+        }
+
         /**
          * @hide
          */
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d93b996..ddff91d 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -295,16 +295,4 @@
      * @hide
      */
     public void childAccessibilityStateChanged(View child);
-
-    /**
-     * A descendant requests this view to find a candidate to take accessibility
-     * focus from hover.
-     *
-     * @param child The child making the call.
-     * @param descendant The descendant that made the initial request.
-     * @return A view to take accessibility focus.
-     *
-     * @hide
-     */
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant);
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ad850da..cd6c502 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -76,8 +76,6 @@
 import com.android.internal.R;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.view.BaseSurfaceHolder;
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.RootViewSurfaceTaker;
 
 import java.io.IOException;
@@ -253,8 +251,6 @@
 
     CompatibilityInfoHolder mCompatibilityInfo;
 
-    /*package*/ int mAddNesting;
-
     // These are accessed by multiple threads.
     final Rect mWinFrame; // frame given by window manager.
 
@@ -1504,7 +1500,8 @@
 
                         if (mAttachInfo.mHardwareRenderer != null) {
                             try {
-                                hwInitialized = mAttachInfo.mHardwareRenderer.initialize(mHolder);
+                                hwInitialized = mAttachInfo.mHardwareRenderer.initialize(
+                                        mHolder.getSurface());
                             } catch (Surface.OutOfResourcesException e) {
                                 Log.e(TAG, "OutOfResourcesException initializing HW surface", e);
                                 try {
@@ -1537,7 +1534,7 @@
                         mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
                     mFullRedrawNeeded = true;
                     try {
-                        mAttachInfo.mHardwareRenderer.updateSurface(mHolder);
+                        mAttachInfo.mHardwareRenderer.updateSurface(mHolder.getSurface());
                     } catch (Surface.OutOfResourcesException e) {
                         Log.e(TAG, "OutOfResourcesException updating HW surface", e);
                         try {
@@ -1628,7 +1625,7 @@
                         mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
                     mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
                     if (!hwInitialized) {
-                        mAttachInfo.mHardwareRenderer.invalidate(mHolder);
+                        mAttachInfo.mHardwareRenderer.invalidate(mHolder.getSurface());
                     }
                 }
             }
@@ -1680,6 +1677,30 @@
                     layoutRequested = true;
                 }
             }
+        } else {
+            // Not the first pass and no window/insets/visibility change but the window
+            // may have moved and we need check that and if so to update the left and right
+            // in the attach info. We translate only the window frame since on window move
+            // the window manager tells us only for the new frame but the insets are the
+            // same and we do not want to translate them more than once.
+
+            // TODO: Well, we are checking whether the frame has changed similarly
+            // to how this is done for the insets. This is however incorrect since
+            // the insets and the frame are translated. For example, the old frame
+            // was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new
+            // reported frame is (2, 2 - 2, 2) which implies no change but this is not
+            // true since we are comparing a not translated value to a translated one.
+            // This scenario is rare but we may want to fix that.
+
+            final boolean windowMoved = (attachInfo.mWindowLeft != frame.left
+                    || attachInfo.mWindowTop != frame.top);
+            if (windowMoved) {
+                if (mTranslator != null) {
+                    mTranslator.translateRectInScreenToAppWinFrame(frame);
+                }
+                attachInfo.mWindowLeft = frame.left;
+                attachInfo.mWindowTop = frame.top;
+            }
         }
 
         final boolean didLayout = layoutRequested && !mStopped;
@@ -2281,14 +2302,6 @@
         return true;
     }
 
-    @Override
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-        if (descendant.includeForAccessibility()) {
-            return descendant;
-        }
-        return null;
-    }
-
     /**
      * We want to draw a highlight around the current accessibility focused.
      * Since adding a style for all possible view is not a viable option we
@@ -2727,6 +2740,7 @@
     private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
     private final static int MSG_DISPATCH_DONE_ANIMATING = 23;
     private final static int MSG_INVALIDATE_WORLD = 24;
+    private final static int MSG_WINDOW_MOVED = 25;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -2778,6 +2792,8 @@
                     return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
                 case MSG_DISPATCH_DONE_ANIMATING:
                     return "MSG_DISPATCH_DONE_ANIMATING";
+                case MSG_WINDOW_MOVED:
+                    return "MSG_WINDOW_MOVED";
             }
             return super.getMessageName(message);
         }
@@ -2822,6 +2838,7 @@
                     if (config != null) {
                         updateConfiguration(config, false);
                     }
+                    // TODO: Should left/top stay unchanged and only change the right/bottom?
                     mWinFrame.left = 0;
                     mWinFrame.right = msg.arg1;
                     mWinFrame.top = 0;
@@ -2838,6 +2855,23 @@
                     requestLayout();
                 }
                 break;
+            case MSG_WINDOW_MOVED:
+                if (mAdded) {
+                    final int w = mWinFrame.width();
+                    final int h = mWinFrame.height();
+                    final int l = msg.arg1;
+                    final int t = msg.arg2;
+                    mWinFrame.left = l;
+                    mWinFrame.right = l + w;
+                    mWinFrame.top = t;
+                    mWinFrame.bottom = t + h;
+
+                    if (mView != null) {
+                        forceLayout(mView);
+                    }
+                    requestLayout();
+                }
+                break;
             case MSG_WINDOW_FOCUS_CHANGED: {
                 if (mAdded) {
                     boolean hasWindowFocus = msg.arg1 != 0;
@@ -2854,7 +2888,7 @@
                             mFullRedrawNeeded = true;
                             try {
                                 mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
-                                        mHolder);
+                                        mHolder.getSurface());
                             } catch (Surface.OutOfResourcesException e) {
                                 Log.e(TAG, "OutOfResourcesException locking surface", e);
                                 try {
@@ -4057,6 +4091,18 @@
         mHandler.sendMessage(msg);
     }
 
+    public void dispatchMoved(int newX, int newY) {
+        if (DEBUG_LAYOUT) Log.v(TAG, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
+        if (mTranslator != null) {
+            PointF point = new PointF(newX, newY);
+            mTranslator.translatePointInScreenToAppWindow(point);
+            newX = (int) (point.x + 0.5);
+            newY = (int) (point.y + 0.5);
+        }
+        Message msg = mHandler.obtainMessage(MSG_WINDOW_MOVED, newX, newY);
+        mHandler.sendMessage(msg);
+    }
+
     /**
      * Represents a pending input event that is waiting in a queue.
      *
@@ -4664,23 +4710,20 @@
         }
     }
     
-    static class InputMethodCallback extends IInputMethodCallback.Stub {
+    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.dispatchImeFinishedEvent(seq, handled);
             }
         }
-
-        public void sessionCreated(IInputMethodSession session) {
-            // Stub -- not for use in the client.
-        }
     }
 
     static class W extends IWindow.Stub {
@@ -4699,6 +4742,14 @@
             }
         }
 
+        @Override
+        public void moved(int newX, int newY) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.dispatchMoved(newX, newY);
+            }
+        }
+
         public void dispatchAppVisibility(boolean visible) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
@@ -5186,15 +5237,13 @@
 
         @Override
         public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
-                int windowLeft, int windowTop, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
-                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5227,15 +5276,13 @@
 
         @Override
         public void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId,
-                int windowLeft, int windowTop, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByViewIdClientThread(accessibilityNodeId, viewId,
-                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5248,15 +5295,13 @@
 
         @Override
         public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
-                int windowLeft, int windowTop, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
-                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5268,15 +5313,14 @@
         }
 
         @Override
-        public void findFocus(long accessibilityNodeId, int focusType, int windowLeft,
-                int windowTop, int interactionId,
+        public void findFocus(long accessibilityNodeId, int focusType, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .findFocusClientThread(accessibilityNodeId, focusType, windowLeft, windowTop,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                    .findFocusClientThread(accessibilityNodeId, focusType, interactionId, callback,
+                            flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5288,15 +5332,14 @@
         }
 
         @Override
-        public void focusSearch(long accessibilityNodeId, int direction, int windowLeft,
-                int windowTop, int interactionId,
+        public void focusSearch(long accessibilityNodeId, int direction, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .focusSearchClientThread(accessibilityNodeId, direction, windowLeft, windowTop,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                    .focusSearchClientThread(accessibilityNodeId, direction, interactionId,
+                            callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 1c5d436..cfcf3c0 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -32,12 +32,18 @@
  * for more information.
  */
 public final class ViewTreeObserver {
+    // Recursive listeners use CopyOnWriteArrayList
     private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
-    private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
     private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
-    private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
-    private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
-    private ArrayList<OnPreDrawListener> mOnPreDrawListeners;
+
+    // Non-recursive listeners use CopyOnWriteArray
+    // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
+    private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
+    private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
+    private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
+    private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
+
+    // These listeners cannot be mutated during dispatch
     private ArrayList<OnDrawListener> mOnDrawListeners;
 
     private boolean mAlive = true;
@@ -147,7 +153,7 @@
          * windows behind it should be placed.
          */
         public final Rect contentInsets = new Rect();
-        
+
         /**
          * Offsets from the frame of the window at which windows behind it
          * are visible.
@@ -166,13 +172,13 @@
          * can be touched.
          */
         public static final int TOUCHABLE_INSETS_FRAME = 0;
-        
+
         /**
          * Option for {@link #setTouchableInsets(int)}: the area inside of
          * the content insets can be touched.
          */
         public static final int TOUCHABLE_INSETS_CONTENT = 1;
-        
+
         /**
          * Option for {@link #setTouchableInsets(int)}: the area inside of
          * the visible insets can be touched.
@@ -195,7 +201,7 @@
         }
 
         int mTouchableInsets;
-        
+
         void reset() {
             contentInsets.setEmpty();
             visibleInsets.setEmpty();
@@ -231,7 +237,7 @@
             mTouchableInsets = other.mTouchableInsets;
         }
     }
-    
+
     /**
      * Interface definition for a callback to be invoked when layout has
      * completed and the client can compute its interior insets.
@@ -363,7 +369,7 @@
         checkIsAlive();
 
         if (mOnGlobalLayoutListeners == null) {
-            mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>();
+            mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
         }
 
         mOnGlobalLayoutListeners.add(listener);
@@ -413,7 +419,7 @@
         checkIsAlive();
 
         if (mOnPreDrawListeners == null) {
-            mOnPreDrawListeners = new ArrayList<OnPreDrawListener>();
+            mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>();
         }
 
         mOnPreDrawListeners.add(listener);
@@ -485,7 +491,7 @@
         checkIsAlive();
 
         if (mOnScrollChangedListeners == null) {
-            mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>();
+            mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>();
         }
 
         mOnScrollChangedListeners.add(listener);
@@ -558,7 +564,7 @@
 
         if (mOnComputeInternalInsetsListeners == null) {
             mOnComputeInternalInsetsListeners =
-                    new CopyOnWriteArrayList<OnComputeInternalInsetsListener>();
+                    new CopyOnWriteArray<OnComputeInternalInsetsListener>();
         }
 
         mOnComputeInternalInsetsListeners.add(listener);
@@ -640,10 +646,16 @@
         // perform the dispatching. The iterator is a safe guard against listeners that
         // could mutate the list by calling the various add/remove methods. This prevents
         // the array from being modified while we iterate it.
-        final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
+        final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
         if (listeners != null && listeners.size() > 0) {
-            for (OnGlobalLayoutListener listener : listeners) {
-                listener.onGlobalLayout();
+            CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    access.get(i).onGlobalLayout();
+                }
+            } finally {
+                listeners.end();
             }
         }
     }
@@ -658,17 +670,17 @@
      */
     @SuppressWarnings("unchecked")
     public final boolean dispatchOnPreDraw() {
-        // NOTE: we *must* clone the listener list to perform the dispatching.
-        // The clone is a safe guard against listeners that
-        // could mutate the list by calling the various add/remove methods. This prevents
-        // the array from being modified while we process it.
         boolean cancelDraw = false;
-        if (mOnPreDrawListeners != null && mOnPreDrawListeners.size() > 0) {
-            final ArrayList<OnPreDrawListener> listeners =
-                    (ArrayList<OnPreDrawListener>) mOnPreDrawListeners.clone();
-            int numListeners = listeners.size();
-            for (int i = 0; i < numListeners; ++i) {
-                cancelDraw |= !(listeners.get(i).onPreDraw());
+        final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners;
+        if (listeners != null && listeners.size() > 0) {
+            CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    cancelDraw |= !(access.get(i).onPreDraw());
+                }
+            } finally {
+                listeners.end();
             }
         }
         return cancelDraw;
@@ -710,10 +722,16 @@
         // perform the dispatching. The iterator is a safe guard against listeners that
         // could mutate the list by calling the various add/remove methods. This prevents
         // the array from being modified while we iterate it.
-        final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
+        final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
         if (listeners != null && listeners.size() > 0) {
-            for (OnScrollChangedListener listener : listeners) {
-                listener.onScrollChanged();
+            CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    access.get(i).onScrollChanged();
+                }
+            } finally {
+                listeners.end();
             }
         }
     }
@@ -722,11 +740,11 @@
      * Returns whether there are listeners for computing internal insets.
      */
     final boolean hasComputeInternalInsetsListeners() {
-        final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
                 mOnComputeInternalInsetsListeners;
         return (listeners != null && listeners.size() > 0);
     }
-    
+
     /**
      * Calls all listeners to compute the current insets.
      */
@@ -735,12 +753,105 @@
         // perform the dispatching. The iterator is a safe guard against listeners that
         // could mutate the list by calling the various add/remove methods. This prevents
         // the array from being modified while we iterate it.
-        final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
                 mOnComputeInternalInsetsListeners;
         if (listeners != null && listeners.size() > 0) {
-            for (OnComputeInternalInsetsListener listener : listeners) {
-                listener.onComputeInternalInsets(inoutInfo);
+            CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    access.get(i).onComputeInternalInsets(inoutInfo);
+                }
+            } finally {
+                listeners.end();
             }
         }
     }
+
+    /**
+     * Copy on write array. This array is not thread safe, and only one loop can
+     * iterate over this array at any given time. This class avoids allocations
+     * until a concurrent modification happens.
+     * 
+     * Usage:
+     * 
+     * CopyOnWriteArray.Access<MyData> access = array.start();
+     * try {
+     *     for (int i = 0; i < access.size(); i++) {
+     *         MyData d = access.get(i);
+     *     }
+     * } finally {
+     *     access.end();
+     * }
+     */
+    static class CopyOnWriteArray<T> {
+        private ArrayList<T> mData = new ArrayList<T>();
+        private ArrayList<T> mDataCopy;
+
+        private final Access<T> mAccess = new Access<T>();
+
+        private boolean mStart;
+
+        static class Access<T> {
+            private ArrayList<T> mData;
+            private int mSize;
+
+            T get(int index) {
+                return mData.get(index);
+            }
+
+            int size() {
+                return mSize;
+            }
+        }
+
+        CopyOnWriteArray() {
+        }
+
+        private ArrayList<T> getArray() {
+            if (mStart) {
+                if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData);
+                return mDataCopy;
+            }
+            return mData;
+        }
+
+        Access<T> start() {
+            if (mStart) throw new IllegalStateException("Iteration already started");
+            mStart = true;
+            mDataCopy = null;
+            mAccess.mData = mData;
+            mAccess.mSize = mData.size();
+            return mAccess;
+        }
+
+        void end() {
+            if (!mStart) throw new IllegalStateException("Iteration not started");
+            mStart = false;
+            if (mDataCopy != null) {
+                mData = mDataCopy;
+            }
+            mDataCopy = null;
+        }
+
+        int size() {
+            return getArray().size();
+        }
+
+        void add(T item) {
+            getArray().add(item);
+        }
+
+        void addAll(CopyOnWriteArray<T> array) {
+            getArray().addAll(array.mData);
+        }
+
+        void remove(T item) {
+            getArray().remove(item);
+        }
+
+        void clear() {
+            getArray().clear();
+        }
+    }
 }
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index cf9bcdd..4d4e985c 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -104,6 +104,9 @@
     private boolean mShowCombinedVolumes;
     private boolean mVoiceCapable;
 
+    // True if we want to play tones on the system stream when the master stream is specified.
+    private final boolean mPlayMasterStreamTones;
+
     /** Dialog containing all the sliders */
     private final Dialog mDialog;
     /** Dialog's content view */
@@ -282,6 +285,13 @@
             mMoreButton.setOnClickListener(this);
         }
 
+        boolean masterVolumeOnly = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_useMasterVolume);
+        boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useVolumeKeySounds);
+
+        mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
+
         listenToRingerMode();
     }
 
@@ -790,7 +800,16 @@
      * Lock on this VolumePanel instance as long as you use the returned ToneGenerator.
      */
     private ToneGenerator getOrCreateToneGenerator(int streamType) {
-        if (streamType == STREAM_MASTER) return null;
+        if (streamType == STREAM_MASTER) {
+            // For devices that use the master volume setting only but still want to
+            // play a volume-changed tone, direct the master volume pseudostream to
+            // the system stream's tone generator.
+            if (mPlayMasterStreamTones) {
+                streamType = AudioManager.STREAM_SYSTEM;
+            } else {
+                return null;
+            }
+        }
         synchronized (this) {
             if (mToneGenerators[streamType] == null) {
                 try {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b0e90db..f57f056 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -18,7 +18,6 @@
 
 import android.app.Application;
 import android.content.Context;
-import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
@@ -27,7 +26,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.SystemProperties;
-import android.util.Slog;
 import android.view.accessibility.AccessibilityEvent;
 
 /**
@@ -119,6 +117,8 @@
      */
     public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
 
+    private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
+
     private final Context mContext;
     
     private TypedArray mWindowStyle;
@@ -126,6 +126,7 @@
     private WindowManager mWindowManager;
     private IBinder mAppToken;
     private String mAppName;
+    private boolean mHardwareAccelerated;
     private Window mContainer;
     private Window mActiveChild;
     private boolean mIsActive = false;
@@ -471,80 +472,63 @@
             boolean hardwareAccelerated) {
         mAppToken = appToken;
         mAppName = appName;
+        mHardwareAccelerated = hardwareAccelerated
+                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
         if (wm == null) {
             wm = WindowManagerImpl.getDefault();
         }
-        mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
+        mWindowManager = ((WindowManagerImpl)wm).makeLocal(this);
     }
 
-    static CompatibilityInfoHolder getCompatInfo(Context context) {
-        Application app = (Application)context.getApplicationContext();
-        return app != null ? app.mLoadedApk.mCompatibilityInfo : new CompatibilityInfoHolder();
+    CompatibilityInfoHolder getCompatibilityInfo() {
+        Application app = (Application)mContext.getApplicationContext();
+        return app != null ? app.mLoadedApk.mCompatibilityInfo : null;
     }
 
-    private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper {
-        private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
-
-        private final boolean mHardwareAccelerated;
-
-        LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) {
-            super(wm, getCompatInfo(mContext));
-            mHardwareAccelerated = hardwareAccelerated ||
-                    SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
-        }
-
-        public boolean isHardwareAccelerated() {
-            return mHardwareAccelerated;
-        }
-        
-        public final void addView(View view, ViewGroup.LayoutParams params) {
-            // Let this throw an exception on a bad params.
-            WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params;
-            CharSequence curTitle = wp.getTitle();
-            if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
-                wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-                if (wp.token == null) {
-                    View decor = peekDecorView();
-                    if (decor != null) {
-                        wp.token = decor.getWindowToken();
-                    }
+    void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
+        CharSequence curTitle = wp.getTitle();
+        if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+            wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+            if (wp.token == null) {
+                View decor = peekDecorView();
+                if (decor != null) {
+                    wp.token = decor.getWindowToken();
                 }
-                if (curTitle == null || curTitle.length() == 0) {
-                    String title;
-                    if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
-                        title="Media";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
-                        title="MediaOvr";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
-                        title="Panel";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
-                        title="SubPanel";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
-                        title="AtchDlg";
-                    } else {
-                        title=Integer.toString(wp.type);
-                    }
-                    if (mAppName != null) {
-                        title += ":" + mAppName;
-                    }
-                    wp.setTitle(title);
-                }
-            } else {
-                if (wp.token == null) {
-                    wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
-                }
-                if ((curTitle == null || curTitle.length() == 0)
-                        && mAppName != null) {
-                    wp.setTitle(mAppName);
-                }
-           }
-            if (wp.packageName == null) {
-                wp.packageName = mContext.getPackageName();
             }
-            if (mHardwareAccelerated) {
-                wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+            if (curTitle == null || curTitle.length() == 0) {
+                String title;
+                if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
+                    title="Media";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
+                    title="MediaOvr";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+                    title="Panel";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
+                    title="SubPanel";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
+                    title="AtchDlg";
+                } else {
+                    title=Integer.toString(wp.type);
+                }
+                if (mAppName != null) {
+                    title += ":" + mAppName;
+                }
+                wp.setTitle(title);
             }
-            super.addView(view, params);
+        } else {
+            if (wp.token == null) {
+                wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
+            }
+            if ((curTitle == null || curTitle.length() == 0)
+                    && mAppName != null) {
+                wp.setTitle(mAppName);
+            }
+        }
+        if (wp.packageName == null) {
+            wp.packageName = mContext.getPackageName();
+        }
+        if (mHardwareAccelerated) {
+            wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
     }
 
@@ -718,6 +702,7 @@
      * per {@link #setFlags}.
      * @param flags The flag bits to be set.
      * @see #setFlags
+     * @see #clearFlags
      */
     public void addFlags(int flags) {
         setFlags(flags, flags);
@@ -728,6 +713,7 @@
      * per {@link #setFlags}.
      * @param flags The flag bits to be cleared.
      * @see #setFlags
+     * @see #addFlags
      */
     public void clearFlags(int flags) {
         setFlags(0, flags);
@@ -749,6 +735,8 @@
      *
      * @param flags The new window flags (see WindowManager.LayoutParams).
      * @param mask Which of the window flag bits to modify.
+     * @see #addFlags
+     * @see #clearFlags
      */
     public void setFlags(int flags, int mask) {
         final WindowManager.LayoutParams attrs = getAttributes();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d94275b..123d9e7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -64,15 +64,7 @@
      * @param view The view to be removed.
      */
     public void removeViewImmediate(View view);
-    
-    /**
-     * Return true if this window manager is configured to request hardware
-     * accelerated windows.  This does <em>not</em> guarantee that they will
-     * actually be accelerated, since that depends on the device supporting them.
-     * @hide
-     */
-    public boolean isHardwareAccelerated();
-    
+
     public static class LayoutParams extends ViewGroup.LayoutParams
             implements Parcelable {
         /**
@@ -162,6 +154,7 @@
             @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA, to = "TYPE_APPLICATION_MEDIA"),
             @ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL, to = "TYPE_APPLICATION_SUB_PANEL"),
             @ViewDebug.IntToString(from = TYPE_APPLICATION_ATTACHED_DIALOG, to = "TYPE_APPLICATION_ATTACHED_DIALOG"),
+            @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA_OVERLAY, to = "TYPE_APPLICATION_MEDIA_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_STATUS_BAR, to = "TYPE_STATUS_BAR"),
             @ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
             @ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
@@ -170,8 +163,6 @@
             @ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, to = "TYPE_STATUS_BAR_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, to = "TYPE_STATUS_BAR_SUB_PANEL"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, to = "TYPE_SYSTEM_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
@@ -185,7 +176,10 @@
             @ViewDebug.IntToString(from = TYPE_POINTER, to = "TYPE_POINTER"),
             @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR, to = "TYPE_NAVIGATION_BAR"),
             @ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY, to = "TYPE_VOLUME_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS")
+            @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS"),
+            @ViewDebug.IntToString(from = TYPE_HIDDEN_NAV_CONSUMER, to = "TYPE_HIDDEN_NAV_CONSUMER"),
+            @ViewDebug.IntToString(from = TYPE_DREAM, to = "TYPE_DREAM"),
+            @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL")
         })
         public int type;
     
@@ -435,6 +429,12 @@
         public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
 
         /**
+         * Window type: Behind the universe of the real windows.
+         * @hide
+         */
+        public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
@@ -530,7 +530,9 @@
         public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
         
         /** Window flag: turn on dithering when compositing this window to
-         *  the screen. */
+         *  the screen.
+         * @deprecated This flag is no longer used. */
+        @Deprecated
         public static final int FLAG_DITHER             = 0x00001000;
         
         /** Window flag: don't allow screen shots while this window is
@@ -718,7 +720,6 @@
          * @see #FLAG_LAYOUT_NO_LIMITS
          * @see #FLAG_FULLSCREEN
          * @see #FLAG_FORCE_NOT_FULLSCREEN
-         * @see #FLAG_DITHER
          * @see #FLAG_SECURE
          * @see #FLAG_SCALED
          * @see #FLAG_IGNORE_CHEEK_PRESSES
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index dd6b537..dedee97 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -18,9 +18,7 @@
 
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
-import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
-import android.graphics.PixelFormat;
 import android.opengl.ManagedEGLContext;
 import android.os.IBinder;
 import android.os.SystemProperties;
@@ -31,7 +29,6 @@
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
-import java.util.HashMap;
 
 final class WindowLeaked extends AndroidRuntimeException {
     public WindowLeaked(String msg) {
@@ -44,7 +41,7 @@
  * the ViewManager interface, allowing you to add any View subclass as a
  * top-level window on the screen. Additional window manager specific layout
  * parameters are defined for control over how windows are displayed.
- * It also implemens the WindowManager interface, allowing you to control the
+ * It also implements the WindowManager interface, allowing you to control the
  * displays attached to the device.
  * 
  * <p>Applications will not normally use WindowManager directly, instead relying
@@ -60,20 +57,25 @@
  * @hide
  */
 public class WindowManagerImpl implements WindowManager {
+    private static final String TAG = "WindowManager";
+
     /**
      * The user is navigating with keys (not the touch screen), so
      * navigational focus should be shown.
      */
     public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
+
     /**
      * This is the first time the window is being drawn,
      * so the client must call drawingFinished() when done
      */
     public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+
     /**
      * The window manager has changed the surface from the last call.
      */
     public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
     /**
      * The window manager is currently animating.  It will call
      * IWindow.doneAnimating() when done.
@@ -108,262 +110,268 @@
     public static final int ADD_MULTIPLE_SINGLETON = -7;
     public static final int ADD_PERMISSION_DENIED = -8;
 
-    private View[] mViews;
-    private ViewRootImpl[] mRoots;
-    private WindowManager.LayoutParams[] mParams;
-    private boolean mNeedsEglTerminate;
+    private static WindowManagerImpl sDefaultWindowManager;
 
-    private Runnable mSystemPropertyUpdater = null;
+    private final WindowManagerState mState;
+    private final Window mParentWindow;
+    private final CompatibilityInfoHolder mCompatibilityInfo;
+    private final Display mDefaultDisplay;
 
-    private final static Object sLock = new Object();
-    private final static WindowManagerImpl sWindowManager = new WindowManagerImpl();
-    private final static HashMap<CompatibilityInfo, WindowManager> sCompatWindowManagers
-            = new HashMap<CompatibilityInfo, WindowManager>();
-
-    static class CompatModeWrapper implements WindowManager {
-        private final WindowManagerImpl mWindowManager;
-        private final Display mDefaultDisplay;
-        private final CompatibilityInfoHolder mCompatibilityInfo;
-
-        CompatModeWrapper(WindowManager wm, CompatibilityInfoHolder ci) {
-            mWindowManager = wm instanceof CompatModeWrapper
-                    ? ((CompatModeWrapper)wm).mWindowManager : (WindowManagerImpl)wm;
-
-            // Use the original display if there is no compatibility mode
-            // to apply, or the underlying window manager is already a
-            // compatibility mode wrapper.  (We assume that if it is a
-            // wrapper, it is applying the same compatibility mode.)
-            if (ci == null) {
-                mDefaultDisplay = mWindowManager.getDefaultDisplay();
-            } else {
-                //mDefaultDisplay = mWindowManager.getDefaultDisplay();
-                mDefaultDisplay = Display.createCompatibleDisplay(
-                        mWindowManager.getDefaultDisplay().getDisplayId(), ci);
-            }
-
-            mCompatibilityInfo = ci;
-        }
-
-        @Override
-        public void addView(View view, android.view.ViewGroup.LayoutParams params) {
-            mWindowManager.addView(view, params, mCompatibilityInfo);
-        }
-
-        @Override
-        public void updateViewLayout(View view, android.view.ViewGroup.LayoutParams params) {
-            mWindowManager.updateViewLayout(view, params);
-
-        }
-
-        @Override
-        public void removeView(View view) {
-            mWindowManager.removeView(view);
-        }
-
-        @Override
-        public Display getDefaultDisplay() {
-            return mDefaultDisplay;
-        }
-
-        @Override
-        public void removeViewImmediate(View view) {
-            mWindowManager.removeViewImmediate(view);
-        }
-
-        @Override
-        public boolean isHardwareAccelerated() {
-            return mWindowManager.isHardwareAccelerated();
-        }
-
+    private WindowManagerImpl(WindowManagerState state, Window parentWindow,
+            CompatibilityInfoHolder compatibilityInfo) {
+        mState = state;
+        mParentWindow = parentWindow;
+        mCompatibilityInfo = compatibilityInfo;
+        mDefaultDisplay = mState.getDefaultDisplay(mCompatibilityInfo);
     }
 
     public static WindowManagerImpl getDefault() {
-        return sWindowManager;
-    }
-
-    public static WindowManager getDefault(CompatibilityInfo compatInfo) {
-        CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
-        cih.set(compatInfo);
-        if (cih.getIfNeeded() == null) {
-            return sWindowManager;
-        }
-
-        synchronized (sLock) {
-            // NOTE: It would be cleaner to move the implementation of
-            // WindowManagerImpl into a static inner class, and have this
-            // public impl just call into that.  Then we can make multiple
-            // instances of WindowManagerImpl for compat mode rather than
-            // having to make wrappers.
-            WindowManager wm = sCompatWindowManagers.get(compatInfo);
-            if (wm == null) {
-                wm = new CompatModeWrapper(sWindowManager, cih);
-                sCompatWindowManagers.put(compatInfo, wm);
+        synchronized (WindowManagerImpl.class) {
+            if (sDefaultWindowManager == null) {
+                sDefaultWindowManager = new WindowManagerImpl(
+                        new WindowManagerState(), null, null);
             }
-            return wm;
+            return sDefaultWindowManager;
         }
     }
 
-    public static WindowManager getDefault(CompatibilityInfoHolder compatInfo) {
-        return new CompatModeWrapper(sWindowManager, compatInfo);
-    }
-    
-    public boolean isHardwareAccelerated() {
-        return false;
-    }
-    
-    public void addView(View view) {
-        addView(view, new WindowManager.LayoutParams(
-            WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE));
+    public WindowManagerImpl makeLocal(Window parentWindow) {
+        return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo());
     }
 
+    public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) {
+        if (compatInfo == mCompatibilityInfo) {
+            return this;
+        }
+        if (compatInfo == null && mParentWindow == null) {
+            return getDefault();
+        }
+        return new WindowManagerImpl(mState, mParentWindow, compatInfo);
+    }
+
+    @Override
     public void addView(View view, ViewGroup.LayoutParams params) {
-        addView(view, params, null, false);
+        mState.addView(view, params, mParentWindow, mCompatibilityInfo);
     }
-    
-    public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih) {
-        addView(view, params, cih, false);
-    }
-    
-    private void addView(View view, ViewGroup.LayoutParams params,
-            CompatibilityInfoHolder cih, boolean nest) {
-        if (false) Log.v("WindowManager", "addView view=" + view);
 
-        if (!(params instanceof WindowManager.LayoutParams)) {
-            throw new IllegalArgumentException(
-                    "Params must be WindowManager.LayoutParams");
+    @Override
+    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+        mState.updateViewLayout(view, params);
+    }
+
+    @Override
+    public void removeView(View view) {
+        mState.removeView(view, false);
+    }
+
+    @Override
+    public void removeViewImmediate(View view) {
+        mState.removeView(view, true);
+    }
+
+    @Override
+    public Display getDefaultDisplay() {
+        return mDefaultDisplay;
+    }
+
+    public void closeAll(IBinder token, String who, String what) {
+        mState.closeAll(token, who, what);
+    }
+
+    public void startTrimMemory(int level) {
+        mState.startTrimMemory(level);
+    }
+
+    public void endTrimMemory() {
+        mState.endTrimMemory();
+    }
+
+    public void trimLocalMemory() {
+        mState.trimLocalMemory();
+    }
+
+    public void dumpGfxInfo(FileDescriptor fd) {
+        mState.dumpGfxInfo(fd);
+    }
+
+    public void setStoppedState(IBinder token, boolean stopped) {
+        mState.setStoppedState(token, stopped);
+    }
+
+    public void reportNewConfiguration(Configuration config) {
+        mState.reportNewConfiguration(config);
+    }
+
+    static final class WindowManagerState {
+        private final Display mDefaultDisplay;
+
+        private View[] mViews;
+        private ViewRootImpl[] mRoots;
+        private WindowManager.LayoutParams[] mParams;
+        private boolean mNeedsEglTerminate;
+
+        private Runnable mSystemPropertyUpdater;
+
+        public WindowManagerState() {
+            mDefaultDisplay = new Display(Display.DEFAULT_DISPLAY, null);
         }
 
-        final WindowManager.LayoutParams wparams
-                = (WindowManager.LayoutParams)params;
-        
-        ViewRootImpl root;
-        View panelParentView = null;
-        
-        synchronized (this) {
-            // Start watching for system property changes.
-            if (mSystemPropertyUpdater == null) {
-                mSystemPropertyUpdater = new Runnable() {
-                    @Override public void run() {
-                        synchronized (this) {
+        public Display getDefaultDisplay(CompatibilityInfoHolder compatInfo) {
+            if (compatInfo == null) {
+                return mDefaultDisplay;
+            }
+            return new Display(Display.DEFAULT_DISPLAY, compatInfo);
+        }
+
+        public void addView(View view, ViewGroup.LayoutParams params, Window parentWindow,
+                CompatibilityInfoHolder cih) {
+            if (!(params instanceof WindowManager.LayoutParams)) {
+                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+            }
+
+            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+            if (parentWindow != null) {
+                parentWindow.adjustLayoutParamsForSubWindow(wparams);
+            }
+
+            ViewRootImpl root;
+            View panelParentView = null;
+
+            synchronized (this) {
+                // Start watching for system property changes.
+                if (mSystemPropertyUpdater == null) {
+                    mSystemPropertyUpdater = new Runnable() {
+                        @Override public void run() {
                             synchronized (this) {
-                                for (ViewRootImpl root : mRoots) {
-                                    root.loadSystemProperties();
+                                synchronized (this) {
+                                    for (ViewRootImpl root : mRoots) {
+                                        root.loadSystemProperties();
+                                    }
                                 }
                             }
                         }
-                    }
-                };
-                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
-            }
+                    };
+                    SystemProperties.addChangeCallback(mSystemPropertyUpdater);
+                }
 
-            // Here's an odd/questionable case: if someone tries to add a
-            // view multiple times, then we simply bump up a nesting count
-            // and they need to remove the view the corresponding number of
-            // times to have it actually removed from the window manager.
-            // This is useful specifically for the notification manager,
-            // which can continually add/remove the same view as a
-            // notification gets updated.
-            int index = findViewLocked(view, false);
-            if (index >= 0) {
-                if (!nest) {
+                int index = findViewLocked(view, false);
+                if (index >= 0) {
                     throw new IllegalStateException("View " + view
                             + " has already been added to the window manager.");
                 }
-                root = mRoots[index];
-                root.mAddNesting++;
-                // Update layout parameters.
+
+                // If this is a panel window, then find the window it is being
+                // attached to for future reference.
+                if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+                        wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+                    final int count = mViews != null ? mViews.length : 0;
+                    for (int i=0; i<count; i++) {
+                        if (mRoots[i].mWindow.asBinder() == wparams.token) {
+                            panelParentView = mViews[i];
+                        }
+                    }
+                }
+
+                root = new ViewRootImpl(view.getContext());
+                if (cih == null) {
+                    root.mCompatibilityInfo = new CompatibilityInfoHolder();
+                } else {
+                    root.mCompatibilityInfo = cih;
+                }
+
                 view.setLayoutParams(wparams);
-                root.setLayoutParams(wparams, true);
-                return;
+
+                if (mViews == null) {
+                    index = 1;
+                    mViews = new View[1];
+                    mRoots = new ViewRootImpl[1];
+                    mParams = new WindowManager.LayoutParams[1];
+                } else {
+                    index = mViews.length + 1;
+                    Object[] old = mViews;
+                    mViews = new View[index];
+                    System.arraycopy(old, 0, mViews, 0, index-1);
+                    old = mRoots;
+                    mRoots = new ViewRootImpl[index];
+                    System.arraycopy(old, 0, mRoots, 0, index-1);
+                    old = mParams;
+                    mParams = new WindowManager.LayoutParams[index];
+                    System.arraycopy(old, 0, mParams, 0, index-1);
+                }
+                index--;
+
+                mViews[index] = view;
+                mRoots[index] = root;
+                mParams[index] = wparams;
             }
-            
-            // If this is a panel window, then find the window it is being
-            // attached to for future reference.
-            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
-                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-                final int count = mViews != null ? mViews.length : 0;
+
+            // do this last because it fires off messages to start doing things
+            root.setView(view, wparams, panelParentView);
+        }
+
+        public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+            if (!(params instanceof WindowManager.LayoutParams)) {
+                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+            }
+
+            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+
+            view.setLayoutParams(wparams);
+
+            synchronized (this) {
+                int index = findViewLocked(view, true);
+                ViewRootImpl root = mRoots[index];
+                mParams[index] = wparams;
+                root.setLayoutParams(wparams, false);
+            }
+        }
+
+        public void removeView(View view, boolean immediate) {
+            synchronized (this) {
+                int index = findViewLocked(view, true);
+                View curView = removeViewLocked(index, immediate);
+                if (curView == view) {
+                    return;
+                }
+
+                throw new IllegalStateException("Calling with view " + view
+                        + " but the ViewAncestor is attached to " + curView);
+            }
+        }
+
+        public void closeAll(IBinder token, String who, String what) {
+            synchronized (this) {
+                if (mViews == null)
+                    return;
+
+                int count = mViews.length;
+                //Log.i("foo", "Closing all windows of " + token);
                 for (int i=0; i<count; i++) {
-                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
-                        panelParentView = mViews[i];
+                    //Log.i("foo", "@ " + i + " token " + mParams[i].token
+                    //        + " view " + mRoots[i].getView());
+                    if (token == null || mParams[i].token == token) {
+                        ViewRootImpl root = mRoots[i];
+
+                        //Log.i("foo", "Force closing " + root);
+                        if (who != null) {
+                            WindowLeaked leak = new WindowLeaked(
+                                    what + " " + who + " has leaked window "
+                                    + root.getView() + " that was originally added here");
+                            leak.setStackTrace(root.getLocation().getStackTrace());
+                            Log.e(TAG, leak.getMessage(), leak);
+                        }
+
+                        removeViewLocked(i, false);
+                        i--;
+                        count--;
                     }
                 }
             }
-            
-            root = new ViewRootImpl(view.getContext());
-            root.mAddNesting = 1;
-            if (cih == null) {
-                root.mCompatibilityInfo = new CompatibilityInfoHolder();
-            } else {
-                root.mCompatibilityInfo = cih;
-            }
-
-            view.setLayoutParams(wparams);
-            
-            if (mViews == null) {
-                index = 1;
-                mViews = new View[1];
-                mRoots = new ViewRootImpl[1];
-                mParams = new WindowManager.LayoutParams[1];
-            } else {
-                index = mViews.length + 1;
-                Object[] old = mViews;
-                mViews = new View[index];
-                System.arraycopy(old, 0, mViews, 0, index-1);
-                old = mRoots;
-                mRoots = new ViewRootImpl[index];
-                System.arraycopy(old, 0, mRoots, 0, index-1);
-                old = mParams;
-                mParams = new WindowManager.LayoutParams[index];
-                System.arraycopy(old, 0, mParams, 0, index-1);
-            }
-            index--;
-
-            mViews[index] = view;
-            mRoots[index] = root;
-            mParams[index] = wparams;
-        }
-        // do this last because it fires off messages to start doing things
-        root.setView(view, wparams, panelParentView);
-    }
-
-    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
-        if (!(params instanceof WindowManager.LayoutParams)) {
-            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
         }
 
-        final WindowManager.LayoutParams wparams
-                = (WindowManager.LayoutParams)params;
-        
-        view.setLayoutParams(wparams);
-
-        synchronized (this) {
-            int index = findViewLocked(view, true);
+        private View removeViewLocked(int index, boolean immediate) {
             ViewRootImpl root = mRoots[index];
-            mParams[index] = wparams;
-            root.setLayoutParams(wparams, false);
-        }
-    }
-
-    public void removeView(View view) {
-        synchronized (this) {
-            int index = findViewLocked(view, true);
-            View curView = removeViewLocked(index);
-            if (curView == view) {
-                return;
-            }
-            
-            throw new IllegalStateException("Calling with view " + view
-                    + " but the ViewAncestor is attached to " + curView);
-        }
-    }
-
-    public void removeViewImmediate(View view) {
-        synchronized (this) {
-            int index = findViewLocked(view, true);
-            ViewRootImpl root = mRoots[index];
-            View curView = root.getView();
-            
-            root.mAddNesting = 0;
+            View view = root.getView();
 
             if (view != null) {
                 InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
@@ -371,289 +379,191 @@
                     imm.windowDismissed(mViews[index].getWindowToken());
                 }
             }
+            root.die(immediate);
 
-            root.die(true);
-            finishRemoveViewLocked(curView, index);
-            if (curView == view) {
-                return;
+            final int count = mViews.length;
+
+            // remove it from the list
+            View[] tmpViews = new View[count-1];
+            removeItem(tmpViews, mViews, index);
+            mViews = tmpViews;
+
+            ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
+            removeItem(tmpRoots, mRoots, index);
+            mRoots = tmpRoots;
+
+            WindowManager.LayoutParams[] tmpParams
+                    = new WindowManager.LayoutParams[count-1];
+            removeItem(tmpParams, mParams, index);
+            mParams = tmpParams;
+
+            if (view != null) {
+                view.assignParent(null);
+                // func doesn't allow null...  does it matter if we clear them?
+                //view.setLayoutParams(null);
             }
-            
-            throw new IllegalStateException("Calling with view " + view
-                    + " but the ViewAncestor is attached to " + curView);
-        }
-    }
-    
-    View removeViewLocked(int index) {
-        ViewRootImpl root = mRoots[index];
-        View view = root.getView();
-
-        // Don't really remove until we have matched all calls to add().
-        root.mAddNesting--;
-        if (root.mAddNesting > 0) {
             return view;
         }
 
-        if (view != null) {
-            InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
-            if (imm != null) {
-                imm.windowDismissed(mViews[index].getWindowToken());
-            }
-        }
-        root.die(false);
-        finishRemoveViewLocked(view, index);
-        return view;
-    }
-    
-    void finishRemoveViewLocked(View view, int index) {
-        final int count = mViews.length;
-
-        // remove it from the list
-        View[] tmpViews = new View[count-1];
-        removeItem(tmpViews, mViews, index);
-        mViews = tmpViews;
-        
-        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
-        removeItem(tmpRoots, mRoots, index);
-        mRoots = tmpRoots;
-        
-        WindowManager.LayoutParams[] tmpParams
-                = new WindowManager.LayoutParams[count-1];
-        removeItem(tmpParams, mParams, index);
-        mParams = tmpParams;
-
-        if (view != null) {
-            view.assignParent(null);
-            // func doesn't allow null...  does it matter if we clear them?
-            //view.setLayoutParams(null);
-        }
-    }
-
-    public void closeAll(IBinder token, String who, String what) {
-        synchronized (this) {
-            if (mViews == null)
-                return;
-            
-            int count = mViews.length;
-            //Log.i("foo", "Closing all windows of " + token);
-            for (int i=0; i<count; i++) {
-                //Log.i("foo", "@ " + i + " token " + mParams[i].token
-                //        + " view " + mRoots[i].getView());
-                if (token == null || mParams[i].token == token) {
-                    ViewRootImpl root = mRoots[i];
-                    root.mAddNesting = 1;
-                    
-                    //Log.i("foo", "Force closing " + root);
-                    if (who != null) {
-                        WindowLeaked leak = new WindowLeaked(
-                                what + " " + who + " has leaked window "
-                                + root.getView() + " that was originally added here");
-                        leak.setStackTrace(root.getLocation().getStackTrace());
-                        Log.e("WindowManager", leak.getMessage(), leak);
-                    }
-
-                    removeViewLocked(i);
-                    i--;
-                    count--;
+        private static void removeItem(Object[] dst, Object[] src, int index) {
+            if (dst.length > 0) {
+                if (index > 0) {
+                    System.arraycopy(src, 0, dst, 0, index);
+                }
+                if (index < dst.length) {
+                    System.arraycopy(src, index+1, dst, index, src.length-index-1);
                 }
             }
         }
-    }
 
-    /**
-     * @param level See {@link android.content.ComponentCallbacks}
-     *
-     * @hide
-     */
-    public void startTrimMemory(int level) {
-        if (HardwareRenderer.isAvailable()) {
-            // On low-end gfx devices we trim when memory is moderate;
-            // on high-end devices we do this when low.
-            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
-                    || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
-                            && !ActivityManager.isHighEndGfx(getDefaultDisplay()))) {
-                // Destroy all hardware surfaces and resources associated to
-                // known windows
-                synchronized (this) {
-                    if (mViews == null) return;
-                    int count = mViews.length;
-                    for (int i = 0; i < count; i++) {
-                        mRoots[i].terminateHardwareResources();
-                    }
-                }
-                // Force a full memory flush
-                mNeedsEglTerminate = true;
-                HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-                return;
-            }
-
-            HardwareRenderer.startTrimMemory(level);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void endTrimMemory() {
-        HardwareRenderer.endTrimMemory();
-
-        if (mNeedsEglTerminate) {
-            ManagedEGLContext.doTerminate();
-            mNeedsEglTerminate = false;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void trimLocalMemory() {
-        synchronized (this) {
-            if (mViews == null) return;
-            int count = mViews.length;
-            for (int i = 0; i < count; i++) {
-                mRoots[i].destroyHardwareLayers();
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void dumpGfxInfo(FileDescriptor fd) {
-        FileOutputStream fout = new FileOutputStream(fd);
-        PrintWriter pw = new PrintWriter(fout);
-        try {
+        private int findViewLocked(View view, boolean required) {
             synchronized (this) {
                 if (mViews != null) {
                     final int count = mViews.length;
-                    
-                    pw.println("Profile data in ms:");
-
                     for (int i = 0; i < count; i++) {
-                        ViewRootImpl root = mRoots[i];
-                        String name = getWindowName(root);
-                        pw.printf("\n\t%s", name);
-
-                        HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
-                        if (renderer != null) {
-                            renderer.dumpGfxInfo(pw);
+                        if (mViews[i] == view) {
+                            return i;
                         }
                     }
+                }
+                if (required) {
+                    throw new IllegalArgumentException("View not attached to window manager");
+                }
+                return -1;
+            }
+        }
 
-                    pw.println("\nView hierarchy:\n");
-
-                    int viewsCount = 0;
-                    int displayListsSize = 0;
-                    int[] info = new int[2];
-
-                    for (int i = 0; i < count; i++) {
-                        ViewRootImpl root = mRoots[i];
-                        root.dumpGfxInfo(info);
-
-                        String name = getWindowName(root);
-                        pw.printf("  %s\n  %d views, %.2f kB of display lists",
-                                name, info[0], info[1] / 1024.0f);
-                        HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
-                        if (renderer != null) {
-                            pw.printf(", %d frames rendered", renderer.getFrameCount());
+        public void startTrimMemory(int level) {
+            if (HardwareRenderer.isAvailable()) {
+                // On low-end gfx devices we trim when memory is moderate;
+                // on high-end devices we do this when low.
+                if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
+                        || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+                                && !ActivityManager.isHighEndGfx(mDefaultDisplay))) {
+                    // Destroy all hardware surfaces and resources associated to
+                    // known windows
+                    synchronized (this) {
+                        if (mViews == null) return;
+                        int count = mViews.length;
+                        for (int i = 0; i < count; i++) {
+                            mRoots[i].terminateHardwareResources();
                         }
-                        pw.printf("\n\n");
-
-                        viewsCount += info[0];
-                        displayListsSize += info[1];
                     }
-
-                    pw.printf("\nTotal ViewRootImpl: %d\n", count);
-                    pw.printf("Total Views:        %d\n", viewsCount);                    
-                    pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);                    
+                    // Force a full memory flush
+                    mNeedsEglTerminate = true;
+                    HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+                    return;
                 }
+
+                HardwareRenderer.startTrimMemory(level);
             }
-        } finally {
-            pw.flush();
-        }        
-    }
+        }
 
-    private static String getWindowName(ViewRootImpl root) {
-        return root.mWindowAttributes.getTitle() + "/" +
-                root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
-    }
+        public void endTrimMemory() {
+            HardwareRenderer.endTrimMemory();
 
-    public void setStoppedState(IBinder token, boolean stopped) {
-        synchronized (this) {
-            if (mViews == null)
-                return;
-            int count = mViews.length;
-            for (int i=0; i<count; i++) {
-                if (token == null || mParams[i].token == token) {
-                    ViewRootImpl root = mRoots[i];
-                    root.setStopped(stopped);
+            if (mNeedsEglTerminate) {
+                ManagedEGLContext.doTerminate();
+                mNeedsEglTerminate = false;
+            }
+        }
+
+        public void trimLocalMemory() {
+            synchronized (this) {
+                if (mViews == null) return;
+                int count = mViews.length;
+                for (int i = 0; i < count; i++) {
+                    mRoots[i].destroyHardwareLayers();
                 }
             }
         }
-    }
-    
-    public void reportNewConfiguration(Configuration config) {
-        synchronized (this) {
-            int count = mViews.length;
-            config = new Configuration(config);
-            for (int i=0; i<count; i++) {
-                ViewRootImpl root = mRoots[i];
-                root.requestUpdateConfiguration(config);
-            }
-        }
-    }
 
-    public WindowManager.LayoutParams getRootViewLayoutParameter(View view) {
-        ViewParent vp = view.getParent();
-        while (vp != null && !(vp instanceof ViewRootImpl)) {
-            vp = vp.getParent();
-        }
-        
-        if (vp == null) return null;
-        
-        ViewRootImpl vr = (ViewRootImpl)vp;
-        
-        int N = mRoots.length;
-        for (int i = 0; i < N; ++i) {
-            if (mRoots[i] == vr) {
-                return mParams[i];
-            }
-        }
-        
-        return null;
-    }
-    
-    public void closeAll() {
-        closeAll(null, null, null);
-    }
-    
-    public Display getDefaultDisplay() {
-        return new Display(Display.DEFAULT_DISPLAY, null);
-    }
+        public void dumpGfxInfo(FileDescriptor fd) {
+            FileOutputStream fout = new FileOutputStream(fd);
+            PrintWriter pw = new PrintWriter(fout);
+            try {
+                synchronized (this) {
+                    if (mViews != null) {
+                        final int count = mViews.length;
 
-    private static void removeItem(Object[] dst, Object[] src, int index) {
-        if (dst.length > 0) {
-            if (index > 0) {
-                System.arraycopy(src, 0, dst, 0, index);
-            }
-            if (index < dst.length) {
-                System.arraycopy(src, index+1, dst, index, src.length-index-1);
+                        pw.println("Profile data in ms:");
+
+                        for (int i = 0; i < count; i++) {
+                            ViewRootImpl root = mRoots[i];
+                            String name = getWindowName(root);
+                            pw.printf("\n\t%s", name);
+
+                            HardwareRenderer renderer =
+                                    root.getView().mAttachInfo.mHardwareRenderer;
+                            if (renderer != null) {
+                                renderer.dumpGfxInfo(pw);
+                            }
+                        }
+
+                        pw.println("\nView hierarchy:\n");
+
+                        int viewsCount = 0;
+                        int displayListsSize = 0;
+                        int[] info = new int[2];
+
+                        for (int i = 0; i < count; i++) {
+                            ViewRootImpl root = mRoots[i];
+                            root.dumpGfxInfo(info);
+
+                            String name = getWindowName(root);
+                            pw.printf("  %s\n  %d views, %.2f kB of display lists",
+                                    name, info[0], info[1] / 1024.0f);
+                            HardwareRenderer renderer =
+                                    root.getView().mAttachInfo.mHardwareRenderer;
+                            if (renderer != null) {
+                                pw.printf(", %d frames rendered", renderer.getFrameCount());
+                            }
+                            pw.printf("\n\n");
+
+                            viewsCount += info[0];
+                            displayListsSize += info[1];
+                        }
+
+                        pw.printf("\nTotal ViewRootImpl: %d\n", count);
+                        pw.printf("Total Views:        %d\n", viewsCount);
+                        pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);
+                    }
+                }
+            } finally {
+                pw.flush();
             }
         }
-    }
 
-    private int findViewLocked(View view, boolean required) {
-        synchronized (this) {
-            final int count = mViews != null ? mViews.length : 0;
-            for (int i=0; i<count; i++) {
-                if (mViews[i] == view) {
-                    return i;
+        private static String getWindowName(ViewRootImpl root) {
+            return root.mWindowAttributes.getTitle() + "/" +
+                    root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
+        }
+
+        public void setStoppedState(IBinder token, boolean stopped) {
+            synchronized (this) {
+                if (mViews != null) {
+                    int count = mViews.length;
+                    for (int i=0; i < count; i++) {
+                        if (token == null || mParams[i].token == token) {
+                            ViewRootImpl root = mRoots[i];
+                            root.setStopped(stopped);
+                        }
+                    }
                 }
             }
-            if (required) {
-                throw new IllegalArgumentException(
-                        "View not attached to window manager");
+        }
+
+        public void reportNewConfiguration(Configuration config) {
+            synchronized (this) {
+                if (mViews != null) {
+                    int count = mViews.length;
+                    config = new Configuration(config);
+                    for (int i=0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        root.requestUpdateConfiguration(config);
+                    }
+                }
             }
-            return -1;
         }
     }
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 09948b8..9522a1b 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -553,7 +553,14 @@
      * allowed to be in.
      */
     public int getMaxWallpaperLayer();
-    
+
+    /**
+     * Return the window layer at which windows appear above the normal
+     * universe (that is no longer impacted by the universe background
+     * transform).
+     */
+    public int getAboveUniverseLayer();
+
     /**
      * Return true if the policy desires a full unified system nav bar.  Otherwise,
      * it is a phone-style status bar with optional nav bar.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 3ad3a55..768744b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -382,10 +382,6 @@
 
     private int mConnectionId = UNDEFINED;
 
-    // TODO: These are a workaround for 6623031. Remove when fixed.
-    private int mActualAndReportedWindowLeftDelta;
-    private int mActualAndReportedWindowTopDelta;
-
     /**
      * Hide constructor from clients.
      */
@@ -432,10 +428,6 @@
         final int rootAccessibilityViewId =
             (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
         mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
-        if (root != null) {
-            mActualAndReportedWindowLeftDelta = root.getActualAndReportedWindowLeftDelta();
-            mActualAndReportedWindowTopDelta = root.getActualAndReportedWindowTopDelta();
-        }
     }
 
     /**
@@ -833,7 +825,6 @@
     public void setBoundsInScreen(Rect bounds) {
         enforceNotSealed();
         mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        mBoundsInScreen.offset(mActualAndReportedWindowLeftDelta, mActualAndReportedWindowTopDelta);
     }
 
     /**
@@ -1343,12 +1334,6 @@
             case View.FOCUS_RIGHT:
             case View.FOCUS_FORWARD:
             case View.FOCUS_BACKWARD:
-            case View.ACCESSIBILITY_FOCUS_DOWN:
-            case View.ACCESSIBILITY_FOCUS_UP:
-            case View.ACCESSIBILITY_FOCUS_LEFT:
-            case View.ACCESSIBILITY_FOCUS_RIGHT:
-            case View.ACCESSIBILITY_FOCUS_FORWARD:
-            case View.ACCESSIBILITY_FOCUS_BACKWARD:
                 return;
             default:
                 throw new IllegalArgumentException("Unknown direction: " + direction);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index b3f3cee..688cbdf 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -132,60 +132,4 @@
             int virtualViewId) {
         return null;
     }
-
-    /**
-     * Finds the accessibility focused {@link AccessibilityNodeInfo}. The search is
-     * relative to the virtual view, i.e. a descendant of the host View, with the
-     * given <code>virtualViewId</code> or the host View itself
-     * <code>virtualViewId</code> equals to {@link View#NO_ID}.
-     *
-     * <strong>Note:</strong> Normally the system is responsible to transparently find
-     *     accessibility focused view starting from a given root but for virtual view
-     *     hierarchies it is a responsibility of this provider's implementor to find
-     *     the accessibility focused virtual view.
-     *
-     * @param virtualViewId A client defined virtual view id which defined
-     *     the root of the tree in which to perform the search.
-     * @return A list of node info.
-     *
-     * @see #createAccessibilityNodeInfo(int)
-     * @see AccessibilityNodeInfo
-     *
-     * @hide
-     */
-    public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
-        return null;
-    }
-
-    /**
-     * Finds {@link AccessibilityNodeInfo} to take accessibility focus in the given
-     * <code>direction</code>. The search is relative to the virtual view, i.e. a
-     * descendant of the host View, with the given <code>virtualViewId</code> or
-     * the host View itself <code>virtualViewId</code> equals to {@link View#NO_ID}.
-     *
-     * <strong>Note:</strong> Normally the system is responsible to transparently find
-     *     the next view to take accessibility focus but for virtual view hierarchies
-     *     it is a responsibility of this provider's implementor to compute the next
-     *     focusable.
-     *
-     * @param direction The direction in which to search for a focus candidate.
-     *     Values are
-     *     {@link View#ACCESSIBILITY_FOCUS_FORWARD},
-     *     {@link View#ACCESSIBILITY_FOCUS_BACKWARD},
-     *     {@link View#ACCESSIBILITY_FOCUS_UP},
-     *     {@link View#ACCESSIBILITY_FOCUS_DOWN},
-     *     {@link View#ACCESSIBILITY_FOCUS_LEFT},
-     *     {@link View#ACCESSIBILITY_FOCUS_RIGHT}.
-     * @param virtualViewId A client defined virtual view id which defined
-     *     the root of the tree in which to perform the search.
-     * @return A list of node info.
-     *
-     * @see #createAccessibilityNodeInfo(int)
-     * @see AccessibilityNodeInfo
-     *
-     * @hide
-     */
-    public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
-        return null;
-    }
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 292702a..9b39300 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -28,25 +28,25 @@
  */
 oneway interface IAccessibilityInteractionConnection {
 
-    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int windowLeft,
-        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        int flags, int interrogatingPid, long interrogatingTid);
+    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int windowLeft,
-        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        int flags, int interrogatingPid, long interrogatingTid);
+    void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int windowLeft,
-        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        int flags, int interrogatingPid, long interrogatingTid);
+    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void findFocus(long accessibilityNodeId, int focusType, int windowLeft, int windowTop,
-        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
-        int interrogatingPid, long interrogatingTid);
+    void findFocus(long accessibilityNodeId, int focusType, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void focusSearch(long accessibilityNodeId, int direction, int windowLeft, int windowTop,
-        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
-        int interrogatingPid, long interrogatingTid);
+    void focusSearch(long accessibilityNodeId, int direction, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
     void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d2cc2d8..58f0b85 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -35,6 +35,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
@@ -225,6 +226,13 @@
      */
     public static final int CONTROL_START_INITIAL = 1<<8;
 
+    /**
+     * Timeout in milliseconds for delivering a key to an IME.
+     */
+    static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
+
+    private static final int MAX_PENDING_EVENT_POOL_SIZE = 4;
+
     final IInputMethodManager mService;
     final Looper mMainLooper;
     
@@ -312,12 +320,17 @@
      */
     IInputMethodSession mCurMethod;
 
+    PendingEvent mPendingEventPool;
+    int mPendingEventPoolSize;
+    PendingEvent mFirstPendingEvent;
+
     // -----------------------------------------------------------
     
     static final int MSG_DUMP = 1;
     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;
     
     class H extends Handler {
         H(Looper looper) {
@@ -342,6 +355,9 @@
                 }
                 case MSG_BIND: {
                     final InputBindResult res = (InputBindResult)msg.obj;
+                    if (DEBUG) {
+                        Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
+                    }
                     synchronized (mH) {
                         if (mBindSequence < 0 || mBindSequence != res.sequence) {
                             Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
@@ -358,6 +374,9 @@
                 }
                 case MSG_UNBIND: {
                     final int sequence = msg.arg1;
+                    if (DEBUG) {
+                        Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence);
+                    }
                     boolean startInput = false;
                     synchronized (mH) {
                         if (mBindSequence == sequence) {
@@ -390,6 +409,9 @@
                 }
                 case MSG_SET_ACTIVE: {
                     final boolean active = msg.arg1 != 0;
+                    if (DEBUG) {
+                        Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
+                    }
                     synchronized (mH) {
                         mActive = active;
                         mFullscreenMode = false;
@@ -407,12 +429,32 @@
                             // Check focus again in case that "onWindowFocus" is called before
                             // handling this message.
                             if (mServedView != null && mServedView.hasWindowFocus()) {
-                                checkFocus(mHasBeenInactive);
+                                // "finishComposingText" has been already called above. So we
+                                // should not call mServedInputConnection.finishComposingText here.
+                                // Also, please note that this handler thread could be different
+                                // from a thread that created mServedView. That could happen
+                                // the current activity is running in the system process.
+                                // In that case, we really should not call
+                                // mServedInputConnection.finishComposingText.
+                                if (checkFocusNoStartInput(mHasBeenInactive, false)) {
+                                    startInputInner(null, 0, 0, 0);
+                                }
                             }
                         }
                     }
                     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);
+                    return;
+                }
             }
         }
     }
@@ -476,6 +518,18 @@
     };    
     
     final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
+
+    final IInputMethodCallback mInputMethodCallback = new IInputMethodCallback.Stub() {
+        @Override
+        public void finishedEvent(int seq, boolean handled) {
+            InputMethodManager.this.finishedEvent(seq, handled);
+        }
+
+        @Override
+        public void sessionCreated(IInputMethodSession session) {
+            // Stub -- not for use in the client.
+        }
+    };
     
     InputMethodManager(IInputMethodManager service, Looper looper) {
         mService = service;
@@ -1105,6 +1159,7 @@
                     if (res.id != null) {
                         mBindSequence = res.sequence;
                         mCurMethod = res.method;
+                        mCurId = res.id;
                     } else if (mCurMethod == null) {
                         // This means there is no input method available.
                         if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
@@ -1194,20 +1249,16 @@
         }
     }
 
-    private void checkFocus(boolean forceNewFocus) {
-        if (checkFocusNoStartInput(forceNewFocus)) {
-            startInputInner(null, 0, 0, 0);
-        }
-    }
-
     /**
      * @hide
      */
     public void checkFocus() {
-        checkFocus(false);
+        if (checkFocusNoStartInput(false, true)) {
+            startInputInner(null, 0, 0, 0);
+        }
     }
 
-    private boolean checkFocusNoStartInput(boolean forceNewFocus) {
+    private boolean checkFocusNoStartInput(boolean forceNewFocus, boolean finishComposingText) {
         // This is called a lot, so short-circuit before locking.
         if (mServedView == mNextServedView && !forceNewFocus) {
             return false;
@@ -1241,7 +1292,7 @@
             mServedConnecting = true;
         }
 
-        if (ic != null) {
+        if (finishComposingText && ic != null) {
             ic.finishComposingText();
         }
 
@@ -1286,7 +1337,7 @@
             controlFlags |= CONTROL_WINDOW_FIRST;
         }
         
-        if (checkFocusNoStartInput(forceNewFocus)) {
+        if (checkFocusNoStartInput(forceNewFocus, true)) {
             // We need to restart input on the current focus view.  This
             // should be done in conjunction with telling the system service
             // about the window gaining focus, to help make the transition
@@ -1511,76 +1562,160 @@
      * @hide
      */
     public void dispatchKeyEvent(Context context, int seq, KeyEvent key,
-            IInputMethodCallback callback) {
+            FinishedEventCallback callback) {
+        boolean handled = false;
         synchronized (mH) {
             if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
-    
-            if (mCurMethod == null) {
-                try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException e) {
-                }
-                return;
-            }
-    
-            if (key.getAction() == KeyEvent.ACTION_DOWN
-                    && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
-                showInputMethodPicker();
-                try {
-                    callback.finishedEvent(seq, true);
-                } catch (RemoteException e) {
-                }
-                return;
-            }
-            try {
-                if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
-                mCurMethod.dispatchKeyEvent(seq, key, callback);
-            } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
-                try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException ex) {
+
+            if (mCurMethod != null) {
+                if (key.getAction() == KeyEvent.ACTION_DOWN
+                        && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
+                    showInputMethodPickerLocked();
+                    handled = true;
+                } else {
+                    try {
+                        if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
+                        final long startTime = SystemClock.uptimeMillis();
+                        mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
+                        enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+                        return;
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
+                    }
                 }
             }
         }
+
+        callback.finishedEvent(seq, handled);
     }
 
     /**
      * @hide
      */
     void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
-            IInputMethodCallback callback) {
+            FinishedEventCallback callback) {
         synchronized (mH) {
             if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
-    
-            if (mCurMethod == null || mCurrentTextBoxAttribute == null) {
+
+            if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
                 try {
-                    callback.finishedEvent(seq, false);
+                    if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
+                    final long startTime = SystemClock.uptimeMillis();
+                    mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
+                    enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+                    return;
                 } catch (RemoteException e) {
-                }
-                return;
-            }
-    
-            try {
-                if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
-                mCurMethod.dispatchTrackballEvent(seq, motion, callback);
-            } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
-                try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException ex) {
+                    Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
                 }
             }
         }
+
+        callback.finishedEvent(seq, false);
+    }
+
+    void finishedEvent(int seq, boolean handled) {
+        final FinishedEventCallback callback;
+        synchronized (mH) {
+            PendingEvent p = dequeuePendingEventLocked(seq);
+            if (p == null) {
+                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);
+    }
+
+    private void enqueuePendingEventLocked(
+            long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
+        PendingEvent p = obtainPendingEventLocked(startTime, seq, inputMethodId, callback);
+        p.mNext = mFirstPendingEvent;
+        mFirstPendingEvent = 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 = mFirstPendingEvent;
+        if (p == null) {
+            return null;
+        }
+        if (p.mSeq == seq) {
+            mFirstPendingEvent = p.mNext;
+        } else {
+            PendingEvent prev;
+            do {
+                prev = p;
+                p = p.mNext;
+                if (p == null) {
+                    return null;
+                }
+            } while (p.mSeq != seq);
+            prev.mNext = p.mNext;
+        }
+        p.mNext = null;
+        return p;
+    }
+
+    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;
+        } 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;
+        }
     }
 
     public void showInputMethodPicker() {
         synchronized (mH) {
-            try {
-                mService.showInputMethodPickerFromClient(mClient);
-            } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-            }
+            showInputMethodPickerLocked();
+        }
+    }
+
+    private void showInputMethodPickerLocked() {
+        try {
+            mService.showInputMethodPickerFromClient(mClient);
+        } catch (RemoteException e) {
+            Log.w(TAG, "IME died: " + mCurId, e);
         }
     }
 
@@ -1773,4 +1908,22 @@
                 + " mCursorCandStart=" + mCursorCandStart
                 + " mCursorCandEnd=" + mCursorCandEnd);
     }
+
+    /**
+     * Callback that is invoked when an input event that was dispatched to
+     * the IME has been finished.
+     * @hide
+     */
+    public interface FinishedEventCallback {
+        public void finishedEvent(int seq, boolean handled);
+    }
+
+    private static final class PendingEvent {
+        public PendingEvent mNext;
+
+        public long mStartTime;
+        public int mSeq;
+        public String mInputMethodId;
+        public FinishedEventCallback mCallback;
+    }
 }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 5108990..fe812af 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -74,6 +74,7 @@
     private final CallbackProxy mCallbackProxy;
     private final WebSettingsClassic mSettings;
     private final Context mContext;
+    private final WebViewDatabaseClassic mDatabase;
     private final WebViewCore mWebViewCore;
     /* package */ boolean mLoadInitFromJava;
     private int mLoadType;
@@ -242,6 +243,7 @@
         mSettings = settings;
         mContext = context;
         mCallbackProxy = proxy;
+        mDatabase = WebViewDatabaseClassic.getInstance(appContext);
         mWebViewCore = w;
 
         mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
@@ -424,8 +426,7 @@
             if (h != null) {
                 String url = WebTextView.urlForAutoCompleteData(h.getUrl());
                 if (url != null) {
-                    WebViewDatabaseClassic.getInstance(mContext).setFormData(
-                            url, data);
+                    mDatabase.setFormData(url, data);
                 }
             }
         }
@@ -497,9 +498,8 @@
                     if (item != null) {
                         WebAddress uri = new WebAddress(item.getUrl());
                         String schemePlusHost = uri.getScheme() + uri.getHost();
-                        String[] up =
-                                WebViewDatabaseClassic.getInstance(mContext)
-                                        .getUsernamePassword(schemePlusHost);
+                        String[] up = mDatabase.getUsernamePassword(
+                                schemePlusHost);
                         if (up != null && up[0] != null) {
                             setUsernamePassword(up[0], up[1]);
                         }
@@ -800,10 +800,10 @@
             // the post data (there could be another form on the
             // page and that was posted instead.
             String postString = new String(postData);
-            WebViewDatabaseClassic db = WebViewDatabaseClassic.getInstance(mContext);
             if (postString.contains(URLEncoder.encode(username)) &&
                     postString.contains(URLEncoder.encode(password))) {
-                String[] saved = db.getUsernamePassword(schemePlusHost);
+                String[] saved = mDatabase.getUsernamePassword(
+                        schemePlusHost);
                 if (saved != null) {
                     // null username implies that user has chosen not to
                     // save password
@@ -811,8 +811,7 @@
                         // non-null username implies that user has
                         // chosen to save password, so update the
                         // recorded password
-                        db.setUsernamePassword(schemePlusHost, username,
-                                password);
+                        mDatabase.setUsernamePassword(schemePlusHost, username, password);
                     }
                 } else {
                     // CallbackProxy will handle creating the resume
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 2d9f60d..8b7cecf 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -71,7 +71,7 @@
     // Start with 100 to indicate it is not in load for the empty page.
     private volatile int mLatestProgress = 100;
     // Back/Forward list
-    private final WebBackForwardList mBackForwardList;
+    private final WebBackForwardListClassic mBackForwardList;
     // Back/Forward list client
     private volatile WebBackForwardListClient mWebBackForwardListClient;
     // Used to call startActivity during url override.
@@ -117,7 +117,6 @@
     private static final int ADD_HISTORY_ITEM                     = 135;
     private static final int HISTORY_INDEX_CHANGED                = 136;
     private static final int AUTH_CREDENTIALS                     = 137;
-    private static final int SET_INSTALLABLE_WEBAPP               = 138;
     private static final int NOTIFY_SEARCHBOX_LISTENERS           = 139;
     private static final int AUTO_LOGIN                           = 140;
     private static final int CLIENT_CERT_REQUEST                  = 141;
@@ -188,7 +187,7 @@
         // Used to start a default activity.
         mContext = context;
         mWebView = w;
-        mBackForwardList = new WebBackForwardList(this);
+        mBackForwardList = new WebBackForwardListClassic(this);
     }
 
     protected synchronized void blockMessages() {
@@ -249,7 +248,7 @@
      * Get the Back/Forward list to return to the user or to update the cached
      * history list.
      */
-    public WebBackForwardList getBackForwardList() {
+    public WebBackForwardListClassic getBackForwardList() {
         return mBackForwardList;
     }
 
@@ -403,17 +402,18 @@
                 break;
 
             case PROCEEDED_AFTER_SSL_ERROR:
-                if (mWebViewClient != null) {
-                    mWebViewClient.onProceededAfterSslError(mWebView.getWebView(),
+                if (mWebViewClient != null && mWebViewClient instanceof WebViewClientClassicExt) {
+                    ((WebViewClientClassicExt) mWebViewClient).onProceededAfterSslError(
+                            mWebView.getWebView(),
                             (SslError) msg.obj);
                 }
                 break;
 
             case CLIENT_CERT_REQUEST:
-                if (mWebViewClient != null) {
-                    HashMap<String, Object> map =
-                        (HashMap<String, Object>) msg.obj;
-                    mWebViewClient.onReceivedClientCertRequest(mWebView.getWebView(),
+                if (mWebViewClient != null  && mWebViewClient instanceof WebViewClientClassicExt) {
+                    HashMap<String, Object> map = (HashMap<String, Object>) msg.obj;
+                    ((WebViewClientClassicExt) mWebViewClient).onReceivedClientCertRequest(
+                            mWebView.getWebView(),
                             (ClientCertRequestHandler) map.get("handler"),
                             (String) map.get("host_and_port"));
                 }
@@ -857,11 +857,6 @@
                         host, realm, username, password);
                 break;
             }
-            case SET_INSTALLABLE_WEBAPP:
-                if (mWebChromeClient != null) {
-                    mWebChromeClient.setInstallableWebApp();
-                }
-                break;
             case NOTIFY_SEARCHBOX_LISTENERS: {
                 SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
 
@@ -1081,7 +1076,7 @@
     }
 
     public void onProceededAfterSslError(SslError error) {
-        if (mWebViewClient == null) {
+        if (mWebViewClient == null || !(mWebViewClient instanceof WebViewClientClassicExt)) {
             return;
         }
         Message msg = obtainMessage(PROCEEDED_AFTER_SSL_ERROR);
@@ -1092,7 +1087,7 @@
     public void onReceivedClientCertRequest(ClientCertRequestHandler handler, String host_and_port) {
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
-        if (mWebViewClient == null) {
+        if (mWebViewClient == null || !(mWebViewClient instanceof WebViewClientClassicExt)) {
             handler.cancel();
             return;
         }
@@ -1301,7 +1296,7 @@
     public void onReceivedIcon(Bitmap icon) {
         // The current item might be null if the icon was already stored in the
         // database and this is a new WebView.
-        WebHistoryItem i = mBackForwardList.getCurrentItem();
+        WebHistoryItemClassic i = mBackForwardList.getCurrentItem();
         if (i != null) {
             i.setFavicon(icon);
         }
@@ -1316,7 +1311,7 @@
     /* package */ void onReceivedTouchIconUrl(String url, boolean precomposed) {
         // We should have a current item but we do not want to crash so check
         // for null.
-        WebHistoryItem i = mBackForwardList.getCurrentItem();
+        WebHistoryItemClassic i = mBackForwardList.getCurrentItem();
         if (i != null) {
             i.setTouchIconUrl(url, precomposed);
         }
@@ -1608,13 +1603,6 @@
         sendMessage(msg);
     }
 
-    void setInstallableWebApp() {
-        if (mWebChromeClient == null) {
-            return;
-        }
-        sendMessage(obtainMessage(SET_INSTALLABLE_WEBAPP));
-    }
-
     boolean canShowAlertDialog() {
         // We can only display the alert dialog if mContext is
         // an Activity context.
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index 4e99335..276bcae 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -86,10 +86,8 @@
             throw new IllegalArgumentException("Invalid context argument");
         }
 
-        JniUtil.setContext(context);
-        Context appContext = context.getApplicationContext();
         if (sRef == null) {
-            sRef = new CookieSyncManager(appContext);
+            sRef = new CookieSyncManager(context);
         }
         return sRef;
     }
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 33eaad6..b16748b 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -75,7 +75,7 @@
     // ratio is correct.
     private int mVideoWidth;
     private int mVideoHeight;
-
+    private boolean mPlayingWhenDestroyed = false;
     SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
     {
         public void surfaceChanged(SurfaceHolder holder, int format,
@@ -101,12 +101,11 @@
 
         public void surfaceDestroyed(SurfaceHolder holder)
         {
-            // After we return from this we can't use the surface any more.
-            // The current Video View will be destroy when we play a new video.
+            mPlayingWhenDestroyed = mPlayer.isPlaying();
             pauseAndDispatch(mProxy);
-            // TODO: handle full screen->inline mode transition without a reload.
-            mPlayer.release();
-            mPlayer = null;
+            // We need to set the display to null before switching into inline
+            // mode to avoid error.
+            mPlayer.setDisplay(null);
             mSurfaceHolder = null;
             if (mMediaController != null) {
                 mMediaController.hide();
@@ -194,18 +193,6 @@
             mCanPause = mCanSeekBack = mCanSeekForward = true;
         }
 
-        if (mProgressView != null) {
-            mProgressView.setVisibility(View.GONE);
-        }
-
-        mVideoWidth = mp.getVideoWidth();
-        mVideoHeight = mp.getVideoHeight();
-        // This will trigger the onMeasure to get the display size right.
-        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
-        // Call into the native to ask for the state, if still in play mode,
-        // this will trigger the video to play.
-        mProxy.dispatchOnRestoreState();
-
         if (getStartWhenPrepared()) {
             mPlayer.start();
             // Clear the flag.
@@ -219,6 +206,16 @@
             mMediaController.setEnabled(true);
             mMediaController.show();
         }
+
+        if (mProgressView != null) {
+            mProgressView.setVisibility(View.GONE);
+        }
+
+        mVideoWidth = mp.getVideoWidth();
+        mVideoHeight = mp.getVideoHeight();
+        // This will trigger the onMeasure to get the display size right.
+        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+
     }
 
     public boolean fullScreenExited() {
@@ -232,7 +229,6 @@
                 // which happens when the video view is detached from its parent
                 // view. This happens in the WebChromeClient before this method
                 // is invoked.
-                mProxy.dispatchOnStopFullScreen();
                 mLayout.removeView(getSurfaceView());
 
                 if (mProgressView != null) {
@@ -242,12 +238,11 @@
                 mLayout = null;
                 // Re enable plugin views.
                 mProxy.getWebView().getViewManager().showAll();
-
-                mProxy = null;
-
                 // Don't show the controller after exiting the full screen.
                 mMediaController = null;
-                mCurrentState = STATE_RESETTED;
+                // Continue the inline mode playing if necessary.
+                mProxy.dispatchOnStopFullScreen(mPlayingWhenDestroyed);
+                mProxy = null;
             }
         };
 
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 2c7ea5d..fee82c9 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -34,8 +34,8 @@
         }
     }
 
-    HTML5VideoInline(int videoLayerId, int position) {
-        init(videoLayerId, position, false);
+    HTML5VideoInline(int videoLayerId, int position, boolean skipPrepare) {
+        init(videoLayerId, position, skipPrepare);
     }
 
     @Override
@@ -84,7 +84,7 @@
         return mSurfaceTexture;
     }
 
-    public boolean surfaceTextureDeleted() {
+    public static boolean surfaceTextureDeleted() {
         return (mSurfaceTexture == null);
     }
 
@@ -110,7 +110,9 @@
     }
 
     private void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) {
-        mSurfaceTexture.setOnFrameAvailableListener(l);
+        if (mSurfaceTexture != null) {
+            mSurfaceTexture.setOnFrameAvailableListener(l);
+        }
     }
 
 }
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 371feea..96d8248 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -35,6 +35,7 @@
     static final int STATE_PREPARED           = 2;
     static final int STATE_PLAYING            = 3;
     static final int STATE_RESETTED           = 4;
+    static final int STATE_RELEASED           = 5;
 
     protected HTML5VideoViewProxy mProxy;
 
@@ -126,7 +127,7 @@
     }
 
     public void reset() {
-        if (mCurrentState != STATE_RESETTED) {
+        if (mCurrentState < STATE_RESETTED) {
             mPlayer.reset();
         }
         mCurrentState = STATE_RESETTED;
@@ -138,6 +139,18 @@
         }
     }
 
+    public static void release() {
+        if (mPlayer != null && mCurrentState != STATE_RELEASED) {
+            mPlayer.release();
+            mPlayer = null;
+        }
+        mCurrentState = STATE_RELEASED;
+    }
+
+    public boolean isReleased() {
+        return mCurrentState == STATE_RELEASED;
+    }
+
     public boolean getPauseDuringPreparing() {
         return mPauseDuringPreparing;
     }
@@ -337,11 +350,6 @@
         // Only used in HTML5VideoFullScreen
     }
 
-    public boolean surfaceTextureDeleted() {
-        // Only meaningful for HTML5VideoInline
-        return false;
-    }
-
     public boolean fullScreenExited() {
         // Only meaningful for HTML5VideoFullScreen
         return false;
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index ab884df..701ef35 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -59,6 +59,7 @@
     private static final int LOAD_DEFAULT_POSTER = 104;
     private static final int BUFFERING_START     = 105;
     private static final int BUFFERING_END       = 106;
+    private static final int ENTER_FULLSCREEN    = 107;
 
     // Message Ids to be handled on the WebCore thread
     private static final int PREPARED          = 200;
@@ -105,12 +106,11 @@
         // When we found the Video layer, then we set the Surface Texture to it.
         // Otherwise, we may want to delete the Surface Texture to save memory.
         public static void setBaseLayer(int layer) {
+            mBaseLayer = layer;
             // Don't do this for full screen mode.
             if (mHTML5VideoView != null
                 && !mHTML5VideoView.isFullScreenMode()
-                && !mHTML5VideoView.surfaceTextureDeleted()) {
-                mBaseLayer = layer;
-
+                && !mHTML5VideoView.isReleased()) {
                 int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
                 SurfaceTexture surfTexture =
                         HTML5VideoInline.getSurfaceTexture(currentVideoLayerId);
@@ -126,7 +126,6 @@
                     if (playerState >= HTML5VideoView.STATE_PREPARED
                             && !foundInTree) {
                         mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                        mHTML5VideoView.deleteSurfaceTexture();
                     }
                 }
             }
@@ -136,9 +135,6 @@
         public static void pauseAndDispatch() {
             if (mHTML5VideoView != null) {
                 mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                // When switching out, clean the video content on the old page
-                // by telling the layer not readyToUseSurfTex.
-                setBaseLayer(mBaseLayer);
             }
         }
 
@@ -217,9 +213,16 @@
                 }
             }
 
+            boolean skipPrepare = false;
+            boolean createInlineView = false;
             if (backFromFullScreenMode
+                && currentVideoLayerId == videoLayerId
+                && !mHTML5VideoView.isReleased()) {
+                skipPrepare = true;
+                createInlineView = true;
+            } else if(backFromFullScreenMode
                 || currentVideoLayerId != videoLayerId
-                || mHTML5VideoView.surfaceTextureDeleted()) {
+                || HTML5VideoInline.surfaceTextureDeleted()) {
                 // Here, we handle the case when switching to a new video,
                 // either inside a WebView or across WebViews
                 // For switching videos within a WebView or across the WebView,
@@ -231,12 +234,18 @@
                     }
                     mHTML5VideoView.reset();
                 }
+                createInlineView = true;
+            }
+            if (createInlineView) {
                 mCurrentProxy = proxy;
-                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time);
+                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, skipPrepare);
 
                 mHTML5VideoView.setVideoURI(url, mCurrentProxy);
                 mHTML5VideoView.prepareDataAndDisplayMode(proxy);
-            } else if (mCurrentProxy == proxy) {
+                return;
+            }
+
+            if (mCurrentProxy == proxy) {
                 // Here, we handle the case when we keep playing with one video
                 if (!mHTML5VideoView.isPlaying()) {
                     mHTML5VideoView.seekTo(time);
@@ -278,9 +287,6 @@
             if (!mHTML5VideoView.isFullScreenMode()) {
                 mHTML5VideoView.start();
             }
-            if (mBaseLayer != 0) {
-                setBaseLayer(mBaseLayer);
-            }
         }
 
         public static void end() {
@@ -333,8 +339,9 @@
         mWebCoreHandler.sendMessage(msg);
     }
 
-    public void dispatchOnStopFullScreen() {
+    public void dispatchOnStopFullScreen(boolean stillPlaying) {
         Message msg = Message.obtain(mWebCoreHandler, STOPFULLSCREEN);
+        msg.arg1 = stillPlaying ? 1 : 0;
         mWebCoreHandler.sendMessage(msg);
     }
 
@@ -369,6 +376,15 @@
                 }
                 break;
             }
+            case ENTER_FULLSCREEN:{
+                String url = (String) msg.obj;
+                WebChromeClient client = mWebView.getWebChromeClient();
+                int videoLayerID = msg.arg1;
+                if (client != null) {
+                    VideoPlayer.enterFullScreenVideo(videoLayerID, url, this, mWebView);
+                }
+                break;
+            }
             case SEEK: {
                 Integer time = (Integer) msg.obj;
                 mSeekPosition = time;
@@ -613,7 +629,7 @@
                         nativeOnTimeupdate(msg.arg1, mNativePointer);
                         break;
                     case STOPFULLSCREEN:
-                        nativeOnStopFullscreen(mNativePointer);
+                        nativeOnStopFullscreen(msg.arg1, mNativePointer);
                         break;
                     case RESTORESTATE:
                         nativeOnRestoreState(mNativePointer);
@@ -664,6 +680,21 @@
     }
 
     /**
+     * Play a video stream in full screen mode.
+     * @param url is the URL of the video stream.
+     */
+    public void enterFullscreenForVideoLayer(String url, int videoLayerID) {
+        if (url == null) {
+            return;
+        }
+
+        Message message = obtainMessage(ENTER_FULLSCREEN);
+        message.arg1 = videoLayerID;
+        message.obj = url;
+        sendMessage(message);
+    }
+
+    /**
      * Seek into the video stream.
      * @param  time is the position in the video stream.
      */
@@ -748,7 +779,7 @@
     private native void nativeOnPaused(int nativePointer);
     private native void nativeOnPosterFetched(Bitmap poster, int nativePointer);
     private native void nativeOnTimeupdate(int position, int nativePointer);
-    private native void nativeOnStopFullscreen(int nativePointer);
+    private native void nativeOnStopFullscreen(int stillPlaying, int nativePointer);
     private native void nativeOnRestoreState(int nativePointer);
     private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture,
             int baseLayer, int videoLayerId, int textureName,
diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java
index 2fbd1d0..b3571aa 100644
--- a/core/java/android/webkit/HttpAuthHandler.java
+++ b/core/java/android/webkit/HttpAuthHandler.java
@@ -19,9 +19,11 @@
 import android.os.Handler;
 
 /**
- * HTTP authentication request that must be handled by the user interface.
- * WebView creates the object and hands it to the current {@link WebViewClient},
- * which must call either {@link #proceed(String, String)} or {@link #cancel()}.
+ * Represents a request for HTTP authentication. Instances of this class are
+ * created by the WebView and passed to
+ * {@link WebViewClient#onReceivedHttpAuthRequest}. The host application must
+ * call either {@link #proceed} or {@link #cancel} to set the WebView's
+ * response to the request.
  */
 public class HttpAuthHandler extends Handler {
 
@@ -32,27 +34,36 @@
     }
 
     /**
-     * @return True if we can use user credentials on record
-     * (ie, if we did not fail trying to use them last time)
+     * Gets whether the credentials stored for the current host (i.e. the host
+     * for which {@link WebViewClient#onReceivedHttpAuthRequest} was called)
+     * are suitable for use. Credentials are not suitable if they have
+     * previously been rejected by the server for the current request.
+     *
+     * @return whether the credentials are suitable for use
+     * @see Webview#getHttpAuthUsernamePassword
      */
     public boolean useHttpAuthUsernamePassword() {
         return false;
     }
 
     /**
-     * Cancel the authorization request.
+     * Instructs the WebView to cancel the authentication request.
      */
     public void cancel() {
     }
 
     /**
-     * Proceed with the authorization with the given credentials.
+     * Instructs the WebView to proceed with the authentication with the given
+     * credentials. Credentials for use with this method can be retrieved from
+     * the WebView's store using {@link WebView#getHttpAuthUsernamePassword}.
      */
     public void proceed(String username, String password) {
     }
 
     /**
-     * return true if the prompt dialog should be suppressed.
+     * Gets whether the prompt dialog should be suppressed.
+     *
+     * @return whether the prompt dialog should be suppressed
      * @hide
      */
     public boolean suppressDialog() {
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index e6eaa14..d9aeb70 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -89,6 +89,7 @@
     private void fireSharedTimer() { 
         // clear the flag so that sharedTimerFired() can set a new timer
         mHasInstantTimer = false;
+        removeMessages(TIMER_MESSAGE);
         sharedTimerFired();
     }
 
diff --git a/core/java/android/webkit/MockGeolocation.java b/core/java/android/webkit/MockGeolocation.java
index fbda492..885c6c2 100644
--- a/core/java/android/webkit/MockGeolocation.java
+++ b/core/java/android/webkit/MockGeolocation.java
@@ -17,21 +17,29 @@
 package android.webkit;
 
 /**
- * This class is simply a container for the methods used to configure WebKit's
- * mock Geolocation service for use in LayoutTests.
+ * Used to configure the mock Geolocation client for the LayoutTests.
  * @hide
  */
 public final class MockGeolocation {
+    private WebViewCore mWebViewCore;
 
-    // Global instance of a MockGeolocation
-    private static MockGeolocation sMockGeolocation;
+    public MockGeolocation(WebViewCore webViewCore) {
+        mWebViewCore = webViewCore;
+    }
+
+    /**
+     * Sets use of the mock Geolocation client. Also resets that client.
+     */
+    public void setUseMock() {
+        nativeSetUseMock(mWebViewCore);
+    }
 
     /**
      * Set the position for the mock Geolocation service.
      */
     public void setPosition(double latitude, double longitude, double accuracy) {
         // This should only ever be called on the WebKit thread.
-        nativeSetPosition(latitude, longitude, accuracy);
+        nativeSetPosition(mWebViewCore, latitude, longitude, accuracy);
     }
 
     /**
@@ -39,21 +47,18 @@
      */
     public void setError(int code, String message) {
         // This should only ever be called on the WebKit thread.
-        nativeSetError(code, message);
+        nativeSetError(mWebViewCore, code, message);
     }
 
-    /**
-     * Get the global instance of MockGeolocation.
-     * @return The global MockGeolocation instance.
-     */
-    public static MockGeolocation getInstance() {
-      if (sMockGeolocation == null) {
-          sMockGeolocation = new MockGeolocation();
-      }
-      return sMockGeolocation;
+    public void setPermission(boolean allow) {
+        // This should only ever be called on the WebKit thread.
+        nativeSetPermission(mWebViewCore, allow);
     }
 
     // Native functions
-    private static native void nativeSetPosition(double latitude, double longitude, double accuracy);
-    private static native void nativeSetError(int code, String message);
+    private static native void nativeSetUseMock(WebViewCore webViewCore);
+    private static native void nativeSetPosition(WebViewCore webViewCore, double latitude,
+            double longitude, double accuracy);
+    private static native void nativeSetError(WebViewCore webViewCore, int code, String message);
+    private static native void nativeSetPermission(WebViewCore webViewCore, boolean allow);
 }
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index c161085..096d4cda 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -16,7 +16,6 @@
 package android.webkit;
 
 import android.graphics.Point;
-import android.graphics.Region;
 import android.webkit.WebViewCore.DrawData;
 
 import java.io.DataInputStream;
@@ -68,6 +67,15 @@
         return draw;
     }
 
+    public static void dumpLayerHierarchy(int baseLayer, OutputStream out, int level) {
+        nativeDumpLayerHierarchy(baseLayer, level, out,
+                new byte[WORKING_STREAM_STORAGE]);
+    }
+
+
+    private static native void nativeDumpLayerHierarchy(int baseLayer, int level,
+            OutputStream out, byte[] storage);
+
     private static native boolean nativeSerializeViewState(int baseLayer,
             OutputStream stream, byte[] storage);
 
diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java
index 79e634e..bfef2e7 100644
--- a/core/java/android/webkit/WebBackForwardList.java
+++ b/core/java/android/webkit/WebBackForwardList.java
@@ -17,7 +17,6 @@
 package android.webkit;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 
 /**
  * This class contains the back/forward list for a WebView.
@@ -25,22 +24,11 @@
  * inspect the entries in the list.
  */
 public class WebBackForwardList implements Cloneable, Serializable {
-    // Current position in the list.
-    private int mCurrentIndex;
-    // ArrayList of WebHistoryItems for maintaining our copy.
-    private ArrayList<WebHistoryItem> mArray;
-    // Flag to indicate that the list is invalid
-    private boolean mClearPending;
-    // CallbackProxy to issue client callbacks.
-    private final CallbackProxy mCallbackProxy;
 
     /**
-     * Construct a back/forward list used by clients of WebView.
+     *  @hide
      */
-    /*package*/ WebBackForwardList(CallbackProxy proxy) {
-        mCurrentIndex = -1;
-        mArray = new ArrayList<WebHistoryItem>();
-        mCallbackProxy = proxy;
+    public WebBackForwardList() {
     }
 
     /**
@@ -49,7 +37,7 @@
      * @return The current history item.
      */
     public synchronized WebHistoryItem getCurrentItem() {
-        return getItemAtIndex(mCurrentIndex);
+        throw new MustOverrideException();
     }
 
     /**
@@ -58,7 +46,7 @@
      * @return The current index from 0...n or -1 if the list is empty.
      */
     public synchronized int getCurrentIndex() {
-        return mCurrentIndex;
+        throw new MustOverrideException();
     }
 
     /**
@@ -67,10 +55,7 @@
      * @param index The index to retrieve.
      */
     public synchronized WebHistoryItem getItemAtIndex(int index) {
-        if (index < 0 || index >= getSize()) {
-            return null;
-        }
-        return mArray.get(index);
+        throw new MustOverrideException();
     }
 
     /**
@@ -78,78 +63,7 @@
      * @return The size of the list.
      */
     public synchronized int getSize() {
-        return mArray.size();
-    }
-
-    /**
-     * Mark the back/forward list as having a pending clear. This is used on the
-     * UI side to mark the list as being invalid during the clearHistory method.
-     */
-    /*package*/ synchronized void setClearPending() {
-        mClearPending = true;
-    }
-
-    /**
-     * Return the status of the clear flag. This is used on the UI side to
-     * determine if the list is valid for checking things like canGoBack.
-     */
-    /*package*/ synchronized boolean getClearPending() {
-        return mClearPending;
-    }
-
-    /**
-     * Add a new history item to the list. This will remove all items after the
-     * current item and append the new item to the end of the list. Called from
-     * the WebCore thread only. Synchronized because the UI thread may be
-     * reading the array or the current index.
-     * @param item A new history item.
-     */
-    /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
-        // Update the current position because we are going to add the new item
-        // in that slot.
-        ++mCurrentIndex;
-        // If the current position is not at the end, remove all history items
-        // after the current item.
-        final int size = mArray.size();
-        final int newPos = mCurrentIndex;
-        if (newPos != size) {
-            for (int i = size - 1; i >= newPos; i--) {
-                final WebHistoryItem h = mArray.remove(i);
-            }
-        }
-        // Add the item to the list.
-        mArray.add(item);
-        if (mCallbackProxy != null) {
-            mCallbackProxy.onNewHistoryItem(item);
-        }
-    }
-
-    /**
-     * Clear the back/forward list. Called from the WebCore thread.
-     */
-    /*package*/ synchronized void close(int nativeFrame) {
-        // Clear the array first because nativeClose will call addHistoryItem
-        // with the current item.
-        mArray.clear();
-        mCurrentIndex = -1;
-        nativeClose(nativeFrame);
-        // Reset the clear flag
-        mClearPending = false;
-    }
-
-    /* Remove the item at the given index. Called by JNI only. */
-    private synchronized void removeHistoryItem(int index) {
-        // XXX: This is a special case. Since the callback is only triggered
-        // when removing the first item, we can assert that the index is 0.
-        // This lets us change the current index without having to query the
-        // native BackForwardList.
-        if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) {
-            throw new AssertionError();
-        }
-        final WebHistoryItem h = mArray.remove(index);
-        // XXX: If we ever add another callback for removing history items at
-        // any index, this will no longer be valid.
-        mCurrentIndex--;
+        throw new MustOverrideException();
     }
 
     /**
@@ -158,39 +72,7 @@
      * webkit package classes.
      */
     protected synchronized WebBackForwardList clone() {
-        WebBackForwardList l = new WebBackForwardList(null);
-        if (mClearPending) {
-            // If a clear is pending, return a copy with only the current item.
-            l.addHistoryItem(getCurrentItem());
-            return l;
-        }
-        l.mCurrentIndex = mCurrentIndex;
-        int size = getSize();
-        l.mArray = new ArrayList<WebHistoryItem>(size);
-        for (int i = 0; i < size; i++) {
-            // Add a copy of each WebHistoryItem
-            l.mArray.add(mArray.get(i).clone());
-        }
-        return l;
+        throw new MustOverrideException();
     }
 
-    /**
-     * Set the new history index.
-     * @param newIndex The new history index.
-     */
-    /*package*/ synchronized void setCurrentIndex(int newIndex) {
-        mCurrentIndex = newIndex;
-        if (mCallbackProxy != null) {
-            mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex);
-        }
-    }
-
-    /**
-     * Restore the history index.
-     */
-    /*package*/ static native synchronized void restoreIndex(int nativeFrame,
-            int index);
-
-    /* Close the native list. */
-    private static native void nativeClose(int nativeFrame);
 }
diff --git a/core/java/android/webkit/WebBackForwardListClassic.java b/core/java/android/webkit/WebBackForwardListClassic.java
new file mode 100644
index 0000000..2a14e6b
--- /dev/null
+++ b/core/java/android/webkit/WebBackForwardListClassic.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/* package */ class WebBackForwardListClassic extends WebBackForwardList implements Cloneable,
+        Serializable {
+
+    // Current position in the list.
+    private int mCurrentIndex;
+    // ArrayList of WebHistoryItems for maintaining our copy.
+    private ArrayList<WebHistoryItemClassic> mArray;
+    // Flag to indicate that the list is invalid
+    private boolean mClearPending;
+    // CallbackProxy to issue client callbacks.
+    private final CallbackProxy mCallbackProxy;
+
+    /*package*/ WebBackForwardListClassic(CallbackProxy proxy) {
+        mCurrentIndex = -1;
+        mArray = new ArrayList<WebHistoryItemClassic>();
+        mCallbackProxy = proxy;
+    }
+
+    public synchronized WebHistoryItemClassic getCurrentItem() {
+        return getItemAtIndex(mCurrentIndex);
+    }
+
+    public synchronized int getCurrentIndex() {
+        return mCurrentIndex;
+    }
+
+    public synchronized WebHistoryItemClassic getItemAtIndex(int index) {
+        if (index < 0 || index >= getSize()) {
+            return null;
+        }
+        return mArray.get(index);
+    }
+
+    public synchronized int getSize() {
+        return mArray.size();
+    }
+
+    /**
+     * Mark the back/forward list as having a pending clear. This is used on the
+     * UI side to mark the list as being invalid during the clearHistory method.
+     */
+    /*package*/ synchronized void setClearPending() {
+        mClearPending = true;
+    }
+
+    /**
+     * Return the status of the clear flag. This is used on the UI side to
+     * determine if the list is valid for checking things like canGoBack.
+     */
+    /*package*/ synchronized boolean getClearPending() {
+        return mClearPending;
+    }
+
+    /**
+     * Add a new history item to the list. This will remove all items after the
+     * current item and append the new item to the end of the list. Called from
+     * the WebCore thread only. Synchronized because the UI thread may be
+     * reading the array or the current index.
+     * @param item A new history item.
+     */
+    /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
+        // Update the current position because we are going to add the new item
+        // in that slot.
+        ++mCurrentIndex;
+        // If the current position is not at the end, remove all history items
+        // after the current item.
+        final int size = mArray.size();
+        final int newPos = mCurrentIndex;
+        if (newPos != size) {
+            for (int i = size - 1; i >= newPos; i--) {
+                final WebHistoryItem h = mArray.remove(i);
+            }
+        }
+        // Add the item to the list.
+        mArray.add((WebHistoryItemClassic) item);
+        if (mCallbackProxy != null) {
+            mCallbackProxy.onNewHistoryItem(item);
+        }
+    }
+
+    /**
+     * Clear the back/forward list. Called from the WebCore thread.
+     */
+    /*package*/ synchronized void close(int nativeFrame) {
+        // Clear the array first because nativeClose will call addHistoryItem
+        // with the current item.
+        mArray.clear();
+        mCurrentIndex = -1;
+        nativeClose(nativeFrame);
+        // Reset the clear flag
+        mClearPending = false;
+    }
+
+    /* Remove the item at the given index. Called by JNI only. */
+    private synchronized void removeHistoryItem(int index) {
+        // XXX: This is a special case. Since the callback is only triggered
+        // when removing the first item, we can assert that the index is 0.
+        // This lets us change the current index without having to query the
+        // native BackForwardList.
+        if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) {
+            throw new AssertionError();
+        }
+        final WebHistoryItem h = mArray.remove(index);
+        // XXX: If we ever add another callback for removing history items at
+        // any index, this will no longer be valid.
+        mCurrentIndex--;
+    }
+
+    public synchronized WebBackForwardListClassic clone() {
+        WebBackForwardListClassic l = new WebBackForwardListClassic(null);
+        if (mClearPending) {
+            // If a clear is pending, return a copy with only the current item.
+            l.addHistoryItem(getCurrentItem());
+            return l;
+        }
+        l.mCurrentIndex = mCurrentIndex;
+        int size = getSize();
+        l.mArray = new ArrayList<WebHistoryItemClassic>(size);
+        for (int i = 0; i < size; i++) {
+            // Add a copy of each WebHistoryItem
+            l.mArray.add(mArray.get(i).clone());
+        }
+        return l;
+    }
+
+    /**
+     * Set the new history index.
+     * @param newIndex The new history index.
+     */
+    /*package*/ synchronized void setCurrentIndex(int newIndex) {
+        mCurrentIndex = newIndex;
+        if (mCallbackProxy != null) {
+            mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex);
+        }
+    }
+
+    /**
+     * Restore the history index.
+     */
+    /*package*/ static native synchronized void restoreIndex(int nativeFrame,
+            int index);
+
+    /* Close the native list. */
+    private static native void nativeClose(int nativeFrame);
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4e8790b..e93db09 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -245,8 +245,8 @@
     }
 
    /**
-    * Tell the client that the quota has been reached for the Application Cache
-    * API and request a new quota. The client must respond by invoking the
+    * Notify the host application that the Application Cache has reached the
+    * maximum size. The client must respond by invoking the
     * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)}
     * method of the supplied {@link WebStorage.QuotaUpdater} instance. The
     * minimum value that can be set for the new quota is the current quota. The
@@ -255,7 +255,7 @@
     * @param requiredStorage The amount of storage required by the Application
     *                        Cache operation that triggered this notification,
     *                        in bytes.
-    * @param quota The quota, in bytes
+    * @param quota the current maximum Application Cache size, in bytes
     * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
     *                     must be used to inform the WebView of the new quota.
     */
@@ -297,7 +297,12 @@
      * will continue to occur if the script does not finish at the next check
      * point.
      * @return boolean Whether the JavaScript execution should be interrupted.
+     * @deprecated This method is no longer supported and will not be invoked.
      */
+    // This method was only called when using the JSC javascript engine. V8 became
+    // the default JS engine with Froyo and support for building with JSC was
+    // removed in b/5495373. V8 does not have a mechanism for making a callback such
+    // as this.
     public boolean onJsTimeout() {
         return true;
     }
@@ -372,13 +377,6 @@
     }
 
     /**
-     * Tell the client that the page being viewed is web app capable,
-     * i.e. has specified the fullscreen-web-app-capable meta tag.
-     * @hide
-     */
-    public void setInstallableWebApp() { }
-
-    /**
      * Tell the client that the page being viewed has an autofillable
      * form and the user would like to set a profile up.
      * @param msg A Message to send once the user has successfully
diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java
index 788d05c..cc9afe0 100644
--- a/core/java/android/webkit/WebHistoryItem.java
+++ b/core/java/android/webkit/WebHistoryItem.java
@@ -18,9 +18,6 @@
 
 import android.graphics.Bitmap;
 
-import java.net.MalformedURLException;
-import java.net.URL;
-
 /**
  * A convenience class for accessing fields in an entry in the back/forward list
  * of a WebView. Each WebHistoryItem is a snapshot of the requested history
@@ -28,67 +25,11 @@
  * @see WebBackForwardList
  */
 public class WebHistoryItem implements Cloneable {
-    // Global identifier count.
-    private static int sNextId = 0;
-    // Unique identifier.
-    private final int mId;
-    // A point to a native WebHistoryItem instance which contains the actual data
-    private int mNativeBridge;
-    // The favicon for this item.
-    private Bitmap mFavicon;
-    // The pre-flattened data used for saving the state.
-    private byte[] mFlattenedData;
-    // The apple-touch-icon url for use when adding the site to the home screen,
-    // as obtained from a <link> element in the page.
-    private String mTouchIconUrlFromLink;
-    // If no <link> is specified, this holds the default location of the
-    // apple-touch-icon.
-    private String mTouchIconUrlServerDefault;
-    // Custom client data that is not flattened or read by native code.
-    private Object mCustomData;
 
     /**
-     * Basic constructor that assigns a unique id to the item. Called by JNI
-     * only.
+     * @hide
      */
-    private WebHistoryItem(int nativeBridge) {
-        synchronized (WebHistoryItem.class) {
-            mId = sNextId++;
-        }
-        mNativeBridge = nativeBridge;
-        nativeRef(mNativeBridge);
-    }
-
-    protected void finalize() throws Throwable {
-        if (mNativeBridge != 0) {
-            nativeUnref(mNativeBridge);
-            mNativeBridge = 0;
-        }
-    }
-
-    /**
-     * Construct a new WebHistoryItem with initial flattened data.
-     * @param data The pre-flattened data coming from restoreState.
-     */
-    /*package*/ WebHistoryItem(byte[] data) {
-        mFlattenedData = data;
-        synchronized (WebHistoryItem.class) {
-            mId = sNextId++;
-        }
-    }
-
-    /**
-     * Construct a clone of a WebHistoryItem from the given item.
-     * @param item The history item to clone.
-     */
-    private WebHistoryItem(WebHistoryItem item) {
-        mFlattenedData = item.mFlattenedData;
-        mId = item.mId;
-        mFavicon = item.mFavicon;
-        mNativeBridge = item.mNativeBridge;
-        if (mNativeBridge != 0) {
-            nativeRef(mNativeBridge);
-        }
+    public WebHistoryItem() {
     }
 
     /**
@@ -100,7 +41,7 @@
      */
     @Deprecated
     public int getId() {
-        return mId;
+        throw new MustOverrideException();
     }
 
     /**
@@ -112,8 +53,7 @@
      * to synchronize this method.
      */
     public String getUrl() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetUrl(mNativeBridge);
+        throw new MustOverrideException();
     }
 
     /**
@@ -123,8 +63,7 @@
      * @return The original url of this history item.
      */
     public String getOriginalUrl() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetOriginalUrl(mNativeBridge);
+        throw new MustOverrideException();
     }
     
     /**
@@ -134,8 +73,7 @@
      * to synchronize this method.
      */
     public String getTitle() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetTitle(mNativeBridge);
+        throw new MustOverrideException();
     }
 
     /**
@@ -145,119 +83,14 @@
      * to synchronize this method.
      */
     public Bitmap getFavicon() {
-        if (mFavicon == null && mNativeBridge != 0) {
-            mFavicon = nativeGetFavicon(mNativeBridge);
-        }
-        return mFavicon;
-    }
-
-    /**
-     * Return the touch icon url.
-     * If no touch icon <link> tag was specified, returns
-     * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
-     * attempts to retrieve the touch icon will handle the case where
-     * that file does not exist. An icon set by a <link> tag is always
-     * used in preference to an icon saved on the server.
-     * @hide
-     */
-    public String getTouchIconUrl() {
-        if (mTouchIconUrlFromLink != null) {
-            return mTouchIconUrlFromLink;
-        } else if (mTouchIconUrlServerDefault != null) {
-            return mTouchIconUrlServerDefault;
-        }
-
-        try {
-            URL url = new URL(getOriginalUrl());
-            mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
-                    "/apple-touch-icon.png").toString();
-        } catch (MalformedURLException e) {
-            return null;
-        }
-        return mTouchIconUrlServerDefault;
-    }
-
-    /**
-     * Return the custom data provided by the client.
-     * @hide
-     */
-    public Object getCustomData() {
-        return mCustomData;
-    }
-
-    /**
-     * Set the custom data field.
-     * @param data An Object containing any data the client wishes to associate
-     *             with the item.
-     * @hide
-     */
-    public void setCustomData(Object data) {
-        // NOTE: WebHistoryItems are used in multiple threads. However, the
-        // public facing apis are all getters with the exception of this one
-        // api. Since this api is exclusive to clients, we don't make any
-        // promises about thread safety.
-        mCustomData = data;
-    }
-
-    /**
-     * Set the favicon.
-     * @param icon A Bitmap containing the favicon for this history item.
-     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
-     * to synchronize this method.
-     */
-    /*package*/ void setFavicon(Bitmap icon) {
-        mFavicon = icon;
-    }
-
-    /**
-     * Set the touch icon url. Will not overwrite an icon that has been
-     * set already from a <link> tag, unless the new icon is precomposed.
-     * @hide
-     */
-    /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
-        if (precomposed || mTouchIconUrlFromLink == null) {
-            mTouchIconUrlFromLink = url;
-        }
-    }
-
-    /**
-     * Get the pre-flattened data.
-     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
-     * to synchronize this method.
-     */
-    /*package*/ byte[] getFlattenedData() {
-        if (mNativeBridge != 0) {
-            return nativeGetFlattenedData(mNativeBridge);
-        }
-        return mFlattenedData;
-    }
-
-    /**
-     * Inflate this item.
-     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
-     * to synchronize this method.
-     */
-    /*package*/ void inflate(int nativeFrame) {
-        mNativeBridge = inflate(nativeFrame, mFlattenedData);
-        mFlattenedData = null;
+        throw new MustOverrideException();
     }
 
     /**
      * Clone the history item for use by clients of WebView.
      */
     protected synchronized WebHistoryItem clone() {
-        return new WebHistoryItem(this);
+        throw new MustOverrideException();
     }
 
-    /* Natively inflate this item, this method is called in the WebCore thread.
-     */
-    private native int inflate(int nativeFrame, byte[] data);
-    private native void nativeRef(int nptr);
-    private native void nativeUnref(int nptr);
-    private native String nativeGetTitle(int nptr);
-    private native String nativeGetUrl(int nptr);
-    private native String nativeGetOriginalUrl(int nptr);
-    private native byte[] nativeGetFlattenedData(int nptr);
-    private native Bitmap nativeGetFavicon(int nptr);
-
 }
diff --git a/core/java/android/webkit/WebHistoryItemClassic.java b/core/java/android/webkit/WebHistoryItemClassic.java
new file mode 100644
index 0000000..1620fbf
--- /dev/null
+++ b/core/java/android/webkit/WebHistoryItemClassic.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.graphics.Bitmap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/* package */ class WebHistoryItemClassic extends WebHistoryItem implements Cloneable {
+    // Global identifier count.
+    private static int sNextId = 0;
+    // Unique identifier.
+    private final int mId;
+    // A point to a native WebHistoryItem instance which contains the actual data
+    private int mNativeBridge;
+    // The favicon for this item.
+    private Bitmap mFavicon;
+    // The pre-flattened data used for saving the state.
+    private byte[] mFlattenedData;
+    // The apple-touch-icon url for use when adding the site to the home screen,
+    // as obtained from a <link> element in the page.
+    private String mTouchIconUrlFromLink;
+    // If no <link> is specified, this holds the default location of the
+    // apple-touch-icon.
+    private String mTouchIconUrlServerDefault;
+    // Custom client data that is not flattened or read by native code.
+    private Object mCustomData;
+
+    /**
+     * Basic constructor that assigns a unique id to the item. Called by JNI
+     * only.
+     */
+    private WebHistoryItemClassic(int nativeBridge) {
+        synchronized (WebHistoryItemClassic.class) {
+            mId = sNextId++;
+        }
+        mNativeBridge = nativeBridge;
+        nativeRef(mNativeBridge);
+    }
+
+    protected void finalize() throws Throwable {
+        if (mNativeBridge != 0) {
+            nativeUnref(mNativeBridge);
+            mNativeBridge = 0;
+        }
+    }
+
+    /**
+     * Construct a new WebHistoryItem with initial flattened data.
+     * @param data The pre-flattened data coming from restoreState.
+     */
+    /*package*/ WebHistoryItemClassic(byte[] data) {
+        mFlattenedData = data;
+        synchronized (WebHistoryItemClassic.class) {
+            mId = sNextId++;
+        }
+    }
+
+    /**
+     * Construct a clone of a WebHistoryItem from the given item.
+     * @param item The history item to clone.
+     */
+    private WebHistoryItemClassic(WebHistoryItemClassic item) {
+        mFlattenedData = item.mFlattenedData;
+        mId = item.mId;
+        mFavicon = item.mFavicon;
+        mNativeBridge = item.mNativeBridge;
+        if (mNativeBridge != 0) {
+            nativeRef(mNativeBridge);
+        }
+    }
+
+    @Deprecated
+    public int getId() {
+        return mId;
+    }
+
+    public String getUrl() {
+        if (mNativeBridge == 0) return null;
+        return nativeGetUrl(mNativeBridge);
+    }
+
+    public String getOriginalUrl() {
+        if (mNativeBridge == 0) return null;
+        return nativeGetOriginalUrl(mNativeBridge);
+    }
+
+    public String getTitle() {
+        if (mNativeBridge == 0) return null;
+        return nativeGetTitle(mNativeBridge);
+    }
+
+    public Bitmap getFavicon() {
+        if (mFavicon == null && mNativeBridge != 0) {
+            mFavicon = nativeGetFavicon(mNativeBridge);
+        }
+        return mFavicon;
+    }
+
+    /**
+     * Return the touch icon url.
+     * If no touch icon <link> tag was specified, returns
+     * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
+     * attempts to retrieve the touch icon will handle the case where
+     * that file does not exist. An icon set by a <link> tag is always
+     * used in preference to an icon saved on the server.
+     * @hide
+     */
+    public String getTouchIconUrl() {
+        if (mTouchIconUrlFromLink != null) {
+            return mTouchIconUrlFromLink;
+        } else if (mTouchIconUrlServerDefault != null) {
+            return mTouchIconUrlServerDefault;
+        }
+
+        try {
+            URL url = new URL(getOriginalUrl());
+            mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
+                    "/apple-touch-icon.png").toString();
+        } catch (MalformedURLException e) {
+            return null;
+        }
+        return mTouchIconUrlServerDefault;
+    }
+
+    /**
+     * Return the custom data provided by the client.
+     * @hide
+     */
+    public Object getCustomData() {
+        return mCustomData;
+    }
+
+    /**
+     * Set the custom data field.
+     * @param data An Object containing any data the client wishes to associate
+     *             with the item.
+     * @hide
+     */
+    public void setCustomData(Object data) {
+        // NOTE: WebHistoryItems are used in multiple threads. However, the
+        // public facing apis are all getters with the exception of this one
+        // api. Since this api is exclusive to clients, we don't make any
+        // promises about thread safety.
+        mCustomData = data;
+    }
+
+    /**
+     * Set the favicon.
+     * @param icon A Bitmap containing the favicon for this history item.
+     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+     * to synchronize this method.
+     */
+    /*package*/ void setFavicon(Bitmap icon) {
+        mFavicon = icon;
+    }
+
+    /**
+     * Set the touch icon url. Will not overwrite an icon that has been
+     * set already from a <link> tag, unless the new icon is precomposed.
+     * @hide
+     */
+    /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
+        if (precomposed || mTouchIconUrlFromLink == null) {
+            mTouchIconUrlFromLink = url;
+        }
+    }
+
+    /**
+     * Get the pre-flattened data.
+     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+     * to synchronize this method.
+     */
+    /*package*/ byte[] getFlattenedData() {
+        if (mNativeBridge != 0) {
+            return nativeGetFlattenedData(mNativeBridge);
+        }
+        return mFlattenedData;
+    }
+
+    /**
+     * Inflate this item.
+     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+     * to synchronize this method.
+     */
+    /*package*/ void inflate(int nativeFrame) {
+        mNativeBridge = inflate(nativeFrame, mFlattenedData);
+        mFlattenedData = null;
+    }
+
+    public synchronized WebHistoryItemClassic clone() {
+        return new WebHistoryItemClassic(this);
+    }
+
+    /* Natively inflate this item, this method is called in the WebCore thread.
+     */
+    private native int inflate(int nativeFrame, byte[] data);
+    private native void nativeRef(int nptr);
+    private native void nativeUnref(int nptr);
+    private native String nativeGetTitle(int nptr);
+    private native String nativeGetUrl(int nptr);
+    private native String nativeGetOriginalUrl(int nptr);
+    private native byte[] nativeGetFlattenedData(int nptr);
+    private native Bitmap nativeGetFavicon(int nptr);
+
+}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index fa3cb20..193e98d 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -94,30 +94,33 @@
     }
 
     /**
-     * Default cache usage pattern. Use with {@link #setCacheMode}.
+     * Default cache usage mode. If the navigation type doesn't impose any
+     * specific behavior, use cached resources when they are available
+     * and not expired, otherwise load resources from the network.
+     * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_DEFAULT = -1;
 
     /**
-     * Normal cache usage pattern. Use with {@link #setCacheMode}.
+     * Normal cache usage mode. Use with {@link #setCacheMode}.
      */
     public static final int LOAD_NORMAL = 0;
 
     /**
-     * Use cache if content is there, even if expired (eg, history nav).
-     * If it is not in the cache, load from network.
+     * Use cached resources when they are available, even if they have expired.
+     * Otherwise load resources from the network.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_CACHE_ELSE_NETWORK = 1;
 
     /**
-     * Don't use the cache, load from network.
+     * Don't use the cache, load from the network.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_NO_CACHE = 2;
 
     /**
-     * Don't use the network, load from cache only.
+     * Don't use the network, load from the cache.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_CACHE_ONLY = 3;
@@ -153,7 +156,8 @@
     }
 
     /**
-     * Enables dumping the pages navigation cache to a text file.
+     * Enables dumping the pages navigation cache to a text file. The default
+     * is false.
      *
      * @deprecated This method is now obsolete.
      */
@@ -165,6 +169,8 @@
     /**
      * Gets whether dumping the navigation cache is enabled.
      *
+     * @return whether dumping the navigation cache is enabled
+     * @see #setNavDump
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -196,6 +202,26 @@
     }
 
     /**
+     * Sets whether the WebView requires a user gesture to play media.
+     * The default is true.
+     *
+     * @param require whether the WebView requires a user gesture to play media
+     */
+    public void setMediaPlaybackRequiresUserGesture(boolean require) {
+        throw new MustOverrideException();
+    }
+
+    /**
+     * Gets whether the WebView requires a user gesture to play media.
+     *
+     * @return true if the WebView requires a user gesture to play media
+     * @see #setMediaPlaybackRequiresUserGesture
+     */
+    public boolean getMediaPlaybackRequiresUserGesture() {
+        throw new MustOverrideException();
+    }
+
+    /**
      * Sets whether the WebView should use its built-in zoom mechanisms. The
      * built-in zoom mechanisms comprise on-screen zoom controls, which are
      * displayed over the WebView's content, and the use of a pinch gesture to
@@ -285,14 +311,18 @@
     }
 
     /**
-     * Sets whether the WebView loads a page with overview mode.
+     * Sets whether the WebView loads pages in overview mode. The default is
+     * false.
      */
     public void setLoadWithOverviewMode(boolean overview) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether this WebView loads pages with overview mode.
+     * Gets whether this WebView loads pages in overview mode.
+     *
+     * @return whether this WebView loads pages in overview mode
+     * @see #setLoadWithOverviewMode
      */
     public boolean getLoadWithOverviewMode() {
         throw new MustOverrideException();
@@ -344,38 +374,45 @@
     }
 
     /**
-     * Sets whether the WebView is saving form data.
+     * Sets whether the WebView should save form data. The default is true,
+     * unless in private browsing mode, when the value is always false.
      */
     public void setSaveFormData(boolean save) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether the WebView is saving form data and displaying prior
-     * entries/autofill++.  Always false in private browsing mode.
+     * Gets whether the WebView saves form data. Always false in private
+     * browsing mode.
+     *
+     * @return whether the WebView saves form data
+     * @see #setSaveFormData
      */
     public boolean getSaveFormData() {
         throw new MustOverrideException();
     }
 
     /**
-     * Stores whether the WebView is saving password.
+     * Sets whether the WebView should save passwords. The default is true.
      */
     public void setSavePassword(boolean save) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether the WebView is saving password.
+     * Gets whether the WebView saves passwords.
+     *
+     * @return whether the WebView saves passwords
+     * @see #setSavePassword
      */
     public boolean getSavePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the text zoom of the page in percent. Default is 100.
+     * Sets the text zoom of the page in percent. The default is 100.
      *
-     * @param textZoom the percent value for increasing or decreasing the text
+     * @param textZoom the text zoom in percent
      */
     public synchronized void setTextZoom(int textZoom) {
         throw new MustOverrideException();
@@ -384,7 +421,7 @@
     /**
      * Gets the text zoom of the page in percent.
      *
-     * @return a percent value describing the text zoom
+     * @return the text zoom of the page in percent
      * @see #setTextSizeZoom
      */
     public synchronized int getTextZoom() {
@@ -392,11 +429,10 @@
     }
 
     /**
-     * Sets the text size of the page.
+     * Sets the text size of the page. The default is {@link TextSize#NORMAL}.
      *
-     * @param t the TextSize value for increasing or decreasing the text
-     * @see WebSettings.TextSize
-     * @deprecated Use {@link #setTextZoom(int)} instead.
+     * @param t the text size as a {@link TextSize} value
+     * @deprecated Use {@link #setTextZoom} instead.
      */
     public synchronized void setTextSize(TextSize t) {
         throw new MustOverrideException();
@@ -404,33 +440,33 @@
 
     /**
      * Gets the text size of the page. If the text size was previously specified
-     * in percent using {@link #setTextZoom(int)}, this will return
-     * the closest matching {@link TextSize}.
+     * in percent using {@link #setTextZoom}, this will return the closest
+     * matching {@link TextSize}.
      *
-     * @return a TextSize enum value describing the text size
-     * @see WebSettings.TextSize
-     * @deprecated Use {@link #getTextZoom()} instead.
+     * @return the text size as a {@link TextSize} value
+     * @see #setTextSize
+     * @deprecated Use {@link #getTextZoom} instead.
      */
     public synchronized TextSize getTextSize() {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the default zoom density of the page. This should be called from UI
-     * thread.
+     * Sets the default zoom density of the page. This must be called from the UI
+     * thread. The default is {@link ZoomDensity#MEDIUM}.
      *
-     * @param zoom a ZoomDensity value
-     * @see WebSettings.ZoomDensity
+     * @param zoom the zoom density
      */
     public void setDefaultZoom(ZoomDensity zoom) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets the default zoom density of the page. This should be called from UI
-     * thread.
-     * @return a ZoomDensity value
-     * @see WebSettings.ZoomDensity
+     * Gets the default zoom density of the page. This should be called from
+     * the UI thread.
+     *
+     * @return the zoom density
+     * @see #setDefaultZoom
      */
     public ZoomDensity getDefaultZoom() {
         throw new MustOverrideException();
@@ -438,6 +474,7 @@
 
     /**
      * Enables using light touches to make a selection and activate mouseovers.
+     * The default is false.
      */
     public void setLightTouchEnabled(boolean enabled) {
         throw new MustOverrideException();
@@ -445,6 +482,9 @@
 
     /**
      * Gets whether light touches are enabled.
+     *
+     * @return whether light touches are enabled
+     * @see #setLightTouchEnabled
      */
     public boolean getLightTouchEnabled() {
         throw new MustOverrideException();
@@ -474,11 +514,16 @@
     }
 
     /**
-     * Tells the WebView about user-agent string.
+     * Sets the user-agent string using an integer code.
+     * <ul>
+     *   <li>0 means the WebView should use an Android user-agent string</li>
+     *   <li>1 means the WebView should use a desktop user-agent string</li>
+     * </ul>
+     * Other values are ignored. The default is an Android user-agent string,
+     * i.e. code value 0.
      *
-     * @param ua 0 if the WebView should use an Android user-agent string,
-     *           1 if the WebView should use a desktop user-agent string
-     * @deprecated Please use setUserAgentString instead.
+     * @param ua the integer code for the user-agent string
+     * @deprecated Please use {@link #setUserAgentString} instead.
      */
     @Deprecated
     public synchronized void setUserAgent(int ua) {
@@ -486,12 +531,17 @@
     }
 
     /**
-     * Gets the user-agent as an int.
+     * Gets the user-agent as an integer code.
+     * <ul>
+     *   <li>-1 means the WebView is using a custom user-agent string set with
+     *   {@link #setUserAgentString}</li>
+     *   <li>0 means the WebView should use an Android user-agent string</li>
+     *   <li>1 means the WebView should use a desktop user-agent string</li>
+     * </ul>
      *
-     * @return 0 if the WebView is using an Android user-agent string,
-     *         1 if the WebView is using a desktop user-agent string,
-     *         -1 if the WebView is using user defined user-agent string
-     * @deprecated Please use getUserAgentString instead.
+     * @return the integer code for the user-agent string
+     * @see #setUserAgent
+     * @deprecated Please use {@link #getUserAgentString} instead.
      */
     @Deprecated
     public synchronized int getUserAgent() {
@@ -499,7 +549,9 @@
     }
 
     /**
-     * Tells the WebView to use the wide viewport.
+     * Tells the WebView to use a wide viewport. The default is false.
+     *
+     * @param use whether to use a wide viewport
      */
     public synchronized void setUseWideViewPort(boolean use) {
         throw new MustOverrideException();
@@ -509,26 +561,28 @@
      * Gets whether the WebView is using a wide viewport.
      *
      * @return true if the WebView is using a wide viewport
+     * @see #setUseWideViewPort
      */
     public synchronized boolean getUseWideViewPort() {
         throw new MustOverrideException();
     }
 
     /**
-     * Tells the WebView whether it supports multiple windows. TRUE means
-     * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     * boolean, Message)} is implemented by the host application.
+     * Sets whether the WebView whether supports multiple windows. If set to
+     * true, {@link WebChromeClient#onCreateWindow} must be implemented by the
+     * host application. The default is false.
+     *
+     * @param support whether to suport multiple windows
      */
     public synchronized void setSupportMultipleWindows(boolean support) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether the WebView is supporting multiple windows.
+     * Gets whether the WebView supports multiple windows.
      *
-     * @return true if the WebView is supporting multiple windows. This means
-     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     *         boolean, Message)} is implemented by the host application.
+     * @return true if the WebView supports multiple windows
+     * @see #setSupportMultipleWindows
      */
     public synchronized boolean supportMultipleWindows() {
         throw new MustOverrideException();
@@ -536,10 +590,9 @@
 
     /**
      * Sets the underlying layout algorithm. This will cause a relayout of the
-     * WebView. The default is NARROW_COLUMNS.
+     * WebView. The default is {@link LayoutAlgorithm#NARROW_COLUMNS}.
      *
-     * @param l a LayoutAlgorithm enum specifying the algorithm to use
-     * @see WebSettings.LayoutAlgorithm
+     * @param l the layout algorithm to use, as a {@link LayoutAlgorithm} value
      */
     public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
         throw new MustOverrideException();
@@ -548,10 +601,8 @@
     /**
      * Gets the current layout algorithm.
      *
-     * @return a LayoutAlgorithm enum value describing the layout algorithm
-     *         being used
+     * @return the layout algorithm in use, as a {@link LayoutAlgorithm} value
      * @see #setLayoutAlgorithm
-     * @see WebSettings.LayoutAlgorithm
      */
     public synchronized LayoutAlgorithm getLayoutAlgorithm() {
         throw new MustOverrideException();
@@ -596,7 +647,7 @@
     }
 
     /**
-     * Sets the sans-serif font family name.
+     * Sets the sans-serif font family name. The default is "sans-serif".
      *
      * @param font a font family name
      */
@@ -608,6 +659,7 @@
      * Gets the sans-serif font family name.
      *
      * @return the sans-serif font family name as a string
+     * @see #setSansSerifFontFamily
      */
     public synchronized String getSansSerifFontFamily() {
         throw new MustOverrideException();
@@ -883,9 +935,9 @@
     public abstract void setAllowFileAccessFromFileURLs(boolean flag);
 
     /**
-     * Tells the WebView to enable plugins.
+     * Sets whether the WebView should enable plugins. The default is false.
      *
-     * @param flag true if the WebView should load plugins
+     * @param flag true if plugins should be enabled
      * @deprecated This method has been deprecated in favor of
      *             {@link #setPluginState}
      */
@@ -898,7 +950,8 @@
      * Tells the WebView to enable, disable, or have plugins on demand. On
      * demand mode means that if a plugin exists that can handle the embedded
      * content, a placeholder icon will be shown instead of the plugin. When
-     * the placeholder is clicked, the plugin will be enabled.
+     * the placeholder is clicked, the plugin will be enabled. The default is
+     * {@link PluginState#OFF}.
      *
      * @param state a PluginState value
      */
@@ -921,23 +974,27 @@
 
     /**
      * Sets the path to where database storage API databases should be saved.
-     * Note that the WebCore Database Tracker only allows the path to be set once.
+     * In order for the database storage API to function correctly, this method
+     * must be called with a path to which the application can write. This
+     * method should only be called once: repeated calls are ignored.
      *
-     * @param databasePath a String path to the directory where databases should
-     *                     be saved. May be the empty string but should never
-     *                     be null.
+     * @param databasePath a path to the directory where databases should be
+     *                     saved.
      */
     // This will update WebCore when the Sync runs in the C++ side.
+    // Note that the WebCore Database Tracker only allows the path to be set
+    // once.
     public synchronized void setDatabasePath(String databasePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the path where the Geolocation permissions database should be saved.
+     * Sets the path where the Geolocation databases should be saved. In order
+     * for Geolocation permissions and cached positions to be persisted, this
+     * method must be called with a path to which the application can write.
      *
-     * @param databasePath a String path to the directory where the Geolocation
-     *                     permissions database should be saved. May be the
-     *                     empty string but should never be null.
+     * @param databasePath a path to the directory where databases should be
+     *                     saved.
      */
     // This will update WebCore when the Sync runs in the C++ side.
     public synchronized void setGeolocationDatabasePath(String databasePath) {
@@ -945,7 +1002,10 @@
     }
 
     /**
-     * Tells the WebView to enable Application Caches API.
+     * Sets whether the Application Caches API should be enabled. The default
+     * is false. Note that in order for the Application Caches API to be
+     * enabled, a valid database path must also be supplied to
+     * {@link #setAppCachePath}.
      *
      * @param flag true if the WebView should enable Application Caches
      */
@@ -954,20 +1014,25 @@
     }
 
     /**
-     * Sets a custom path to the Application Caches files. The client
-     * must ensure it exists before this call.
+     * Sets the path to the Application Caches files. In order for the
+     * Application Caches API to be enabled, this method must be called with a
+     * path to which the application can write. This method should only be
+     * called once: repeated calls are ignored.
      *
      * @param appCachePath a String path to the directory containing
-     *                     Application Caches files. The appCache path can be
-     *                     the empty string but should not be null. Passing
-     *                     null for this parameter will result in a no-op.
+     *                     Application Caches files.
+     * @see setAppCacheEnabled
      */
     public synchronized void setAppCachePath(String appCachePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the maximum size for the Application Caches content.
+     * Sets the maximum size for the Application Cache content. The passed size
+     * will be rounded to the nearest value that the database can support, so
+     * this should be viewed as a guide, not a hard limit. Setting the
+     * size to a value less than current database size does not cause the
+     * database to be trimmed. The default size is {@link Long#MAX_VALUE}.
      *
      * @param appCacheMaxSize the maximum size in bytes
      */
@@ -976,7 +1041,9 @@
     }
 
     /**
-     * Sets whether the database storage API is enabled.
+     * Sets whether the database storage API is enabled. The default value is
+     * false. See also {@link #setDatabasePath} for how to correctly set up the
+     * database storage API.
      *
      * @param flag true if the WebView should use the database storage API
      */
@@ -985,7 +1052,7 @@
     }
 
     /**
-     * Sets whether the DOM storage API is enabled.
+     * Sets whether the DOM storage API is enabled. The default value is false.
      *
      * @param flag true if the WebView should use the DOM storage API
      */
@@ -997,15 +1064,16 @@
      * Gets whether the DOM Storage APIs are enabled.
      *
      * @return true if the DOM Storage APIs are enabled
+     * @see #setDomStorageEnabled
      */
     public synchronized boolean getDomStorageEnabled() {
         throw new MustOverrideException();
     }
     /**
-     * Gets the path to where database storage API databases are saved for
-     * the current WebView.
+     * Gets the path to where database storage API databases are saved.
      *
      * @return the String path to the database storage API databases
+     * @see #setDatabasePath
      */
     public synchronized String getDatabasePath() {
         throw new MustOverrideException();
@@ -1015,13 +1083,16 @@
      * Gets whether the database storage API is enabled.
      *
      * @return true if the database storage API is enabled
+     * @see #setDatabaseEnabled
      */
     public synchronized boolean getDatabaseEnabled() {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets whether Geolocation is enabled.
+     * Sets whether Geolocation is enabled. The default is true. See also
+     * {@link #setGeolocationDatabasePath} for how to correctly set up
+     * Geolocation.
      *
      * @param flag whether Geolocation should be enabled
      */
@@ -1064,6 +1135,7 @@
      * Gets whether plugins are enabled.
      *
      * @return true if plugins are enabled
+     * @see #setPluginsEnabled
      * @deprecated This method has been replaced by {@link #getPluginState}
      */
     @Deprecated
@@ -1072,9 +1144,10 @@
     }
 
     /**
-     * Gets the current plugin state.
+     * Gets the current state regarding whether plugins are enabled.
      *
-     * @return a value corresponding to the enum PluginState
+     * @return the plugin state as a {@link PluginState} value
+     * @see #setPluginState
      */
     public synchronized PluginState getPluginState() {
         throw new MustOverrideException();
@@ -1135,8 +1208,8 @@
     }
 
     /**
-     * Sets the WebView's user-agent string. If the string "ua" is null or empty,
-     * it will use the system default user-agent string.
+     * Sets the WebView's user-agent string. If the string is null or empty,
+     * the system default value will be used.
      */
     public synchronized void setUserAgentString(String ua) {
         throw new MustOverrideException();
@@ -1144,6 +1217,9 @@
 
     /**
      * Gets the WebView's user-agent string.
+     *
+     * @return the WebView's user-agent string
+     * @see #setUserAgentString
      */
     public synchronized String getUserAgentString() {
         throw new MustOverrideException();
@@ -1151,7 +1227,8 @@
 
     /**
      * Tells the WebView whether it needs to set a node to have focus when
-     * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
+     * {@link WebView#requestFocus(int, android.graphics.Rect)} is called. The
+     * default value is true.
      *
      * @param flag whether the WebView needs to set a node
      */
@@ -1161,9 +1238,10 @@
 
     /**
      * Sets the priority of the Render thread. Unlike the other settings, this
-     * one only needs to be called once per process. The default is NORMAL.
+     * one only needs to be called once per process. The default value is
+     * {@link RenderPriority#NORMAL}.
      *
-     * @param priority a RenderPriority
+     * @param priority the priority
      */
     public synchronized void setRenderPriority(RenderPriority priority) {
         throw new MustOverrideException();
@@ -1171,20 +1249,25 @@
 
     /**
      * Overrides the way the cache is used. The way the cache is used is based
-     * on the navigation option. For a normal page load, the cache is checked
+     * on the navigation type. For a normal page load, the cache is checked
      * and content is re-validated as needed. When navigating back, content is
-     * not revalidated, instead the content is just pulled from the cache.
-     * This function allows the client to override this behavior.
+     * not revalidated, instead the content is just retrieved from the cache.
+     * This method allows the client to override this behavior by specifying
+     * one of {@link #LOAD_DEFAULT}, {@link #LOAD_NORMAL},
+     * {@link #LOAD_CACHE_ELSE_NETWORK}, {@link #LOAD_NO_CACHE} or
+     * {@link #LOAD_CACHE_ONLY}. The default value is {@link #LOAD_DEFAULT}.
      *
-     * @param mode one of the LOAD_ values
+     * @param mode the mode to use
      */
     public void setCacheMode(int mode) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets the current setting for overriding the cache mode. For a full
-     * description, see the {@link #setCacheMode(int)} function.
+     * Gets the current setting for overriding the cache mode.
+     *
+     * @return the current setting for overriding the cache mode
+     * @see #setCacheMode
      */
     public int getCacheMode() {
         throw new MustOverrideException();
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 1288613..66651f7 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -34,7 +34,7 @@
  */
 public class WebSettingsClassic extends WebSettings {
     // TODO: Keep this up to date
-    private static final String PREVIOUS_VERSION = "4.0.4";
+    private static final String PREVIOUS_VERSION = "4.1.1";
 
     // WebView associated with this WebSettings.
     private WebViewClassic mWebView;
@@ -116,6 +116,7 @@
     private boolean         mNeedInitialFocus = true;
     private boolean         mNavDump = false;
     private boolean         mSupportZoom = true;
+    private boolean         mMediaPlaybackRequiresUserGesture = true;
     private boolean         mBuiltInZoomControls = false;
     private boolean         mDisplayZoomControls = true;
     private boolean         mAllowFileAccess = true;
@@ -459,6 +460,25 @@
     }
 
     /**
+     * @see android.webkit.WebSettings#setMediaPlaybackRequiresUserGesture(boolean)
+     */
+    @Override
+    public void setMediaPlaybackRequiresUserGesture(boolean support) {
+        if (mMediaPlaybackRequiresUserGesture != support) {
+            mMediaPlaybackRequiresUserGesture = support;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getMediaPlaybackRequiresUserGesture()
+     */
+    @Override
+    public boolean getMediaPlaybackRequiresUserGesture() {
+        return mMediaPlaybackRequiresUserGesture;
+    }
+
+    /**
      * @see android.webkit.WebSettings#setBuiltInZoomControls(boolean)
      */
     @Override
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 76674f4..1e955bd 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -23,17 +23,22 @@
  * {@link WebView}. It manages the Application Cache API, the Web SQL Database
  * API and the HTML5 Web Storage API.
  *
- * The Web SQL Database API provides storage which is private to a given
- * origin, where an origin comprises the host, scheme and port of a URI.
- * Similarly, use of the Application Cache API can be attributed to an origin.
- * This class provides access to the storage use and quotas for these APIs for
- * a given origin. Origins are represented using {@link WebStorage.Origin}.
+ * The Application Cache API provides a mechanism to create and maintain an
+ * application cache to power offline Web applications. Use of the Application
+ * Cache API can be attributed to an origin {@link WebStorage.Origin}, however
+ * it is not possible to set per-origin quotas. Note that there can be only
+ * one application cache per application.
+ *
+ * The Web SQL Database API provides storage which is private to a given origin.
+ * Similar to the Application Cache, use of the Web SQL Database can be attributed
+ * to an origin. It is also possible to set per-origin quotas.
  */
 public class WebStorage {
 
     /**
      * Encapsulates a callback function which is used to provide a new quota
-     * for a JavaScript storage API. See
+     * for a JavaScript storage API.
+     * See
      * {@link WebChromeClient#onExceededDatabaseQuota} and
      * {@link WebChromeClient#onReachedMaxAppCacheSize}.
      */
@@ -54,6 +59,7 @@
     /**
      * This class encapsulates information about the amount of storage
      * currently used by an origin for the JavaScript storage APIs.
+     * An origin comprises the host, scheme and port of a URI.
      * See {@link WebStorage} for details.
      */
     public static class Origin {
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index 38b5e5c..d3ec603 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -37,9 +37,6 @@
     // handler of the sync thread
     protected Handler mHandler;
     // database for the persistent storage
-    // Note that this remains uninitialised as it is unused. We cannot remove
-    // the member as it leaked into the public API via CookieSyncManager.
-    // TODO: hide this member, ditto for mHandler.
     protected WebViewDatabase mDataBase;
     // Ref count for calls to start/stop sync
     private int mStartSyncRefCount;
@@ -65,6 +62,7 @@
     protected WebSyncManager(Context context, String name) {
         mThreadName = name;
         if (context != null) {
+            mDataBase = WebViewDatabase.getInstance(context);
             mSyncThread = new Thread(this);
             mSyncThread.setName(mThreadName);
             mSyncThread.start();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e493653..6e4e82c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -35,8 +35,8 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewDebug;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -44,6 +44,7 @@
 import android.view.inputmethod.InputConnection;
 import android.widget.AbsoluteLayout;
 
+import java.io.BufferedWriter;
 import java.io.File;
 import java.util.Map;
 
@@ -263,7 +264,7 @@
 @Widget
 public class WebView extends AbsoluteLayout
         implements ViewTreeObserver.OnGlobalFocusChangeListener,
-        ViewGroup.OnHierarchyChangeListener {
+        ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {
 
     private static final String LOGTAG = "webview_proxy";
 
@@ -332,16 +333,12 @@
     @Deprecated
     public interface PictureListener {
         /**
-         * Notifies the listener that the picture has changed.
+         * Used to provide notification that the WebView's picture has changed.
+         * See {@link WebView#capturePicture} for details of the picture.
          *
          * @param view the WebView that owns the picture
          * @param picture the new picture
-         * @deprecated Due to internal changes, the picture does not include
-         *             composited layers such as fixed position elements or
-         *             scrollable divs. While the PictureListener API can still
-         *             be used to detect changes in the WebView content, you
-         *             are advised against its usage until a replacement is
-         *             provided in a future Android release.
+         * @deprecated Deprecated due to internal changes.
          */
         @Deprecated
         public void onNewPicture(WebView view, Picture picture);
@@ -585,12 +582,16 @@
     //-------------------------------------------------------------------------
 
     /**
-     * Saves the username and password for a particular host in this WebView's
-     * internal database.
+     * Sets a username and password pair for the specified host. This data is
+     * used by the Webview to autocomplete username and password fields in web
+     * forms. Note that this is unrelated to the credentials used for HTTP
+     * authentication.
      *
      * @param host the host that required the credentials
      * @param username the username for the given host
      * @param password the password for the given host
+     * @see WebViewDatabase#clearUsernamePassword
+     * @see WebViewDatabase#hasUsernamePassword
      */
     public void savePassword(String host, String username, String password) {
         checkThread();
@@ -598,13 +599,17 @@
     }
 
     /**
-     * Sets the HTTP authentication credentials for a given host and realm.
+     * Stores HTTP authentication credentials for a given host and realm. This
+     * method is intended to be used with
+     * {@link WebViewClient#onReceivedHttpAuthRequest}.
      *
-     * @param host the host for the credentials
-     * @param realm the realm for the credentials
-     * @param username the username for the password. If it is null, it means
-     *                 password can't be saved.
+     * @param host the host to which the credentials apply
+     * @param realm the realm to which the credentials apply
+     * @param username the username
      * @param password the password
+     * @see getHttpAuthUsernamePassword
+     * @see WebViewDatabase#hasHttpAuthUsernamePassword
+     * @see WebViewDatabase#clearHttpAuthUsernamePassword
      */
     public void setHttpAuthUsernamePassword(String host, String realm,
             String username, String password) {
@@ -613,13 +618,18 @@
     }
 
     /**
-     * Retrieves the HTTP authentication username and password for a given
-     * host and realm pair
+     * Retrieves HTTP authentication credentials for a given host and realm.
+     * This method is intended to be used with
+     * {@link WebViewClient#onReceivedHttpAuthRequest}.
      *
-     * @param host the host for which the credentials apply
-     * @param realm the realm for which the credentials apply
-     * @return String[] if found. String[0] is username, which can be null and
-     *         String[1] is password. Return null if it can't find anything.
+     * @param host the host to which the credentials apply
+     * @param realm the realm to which the credentials apply
+     * @return the credentials as a String array, if found. The first element
+     *         is the username and the second element is the password. Null if
+     *         no credentials are found.
+     * @see setHttpAuthUsernamePassword
+     * @see WebViewDatabase#hasHttpAuthUsernamePassword
+     * @see WebViewDatabase#clearHttpAuthUsernamePassword
      */
     public String[] getHttpAuthUsernamePassword(String host, String realm) {
         checkThread();
@@ -723,9 +733,9 @@
     }
 
     /**
-     * Restores the state of this WebView from the given map used in
-     * {@link android.app.Activity#onRestoreInstanceState}. This method should
-     * be called to restore the state of this WebView before using the object. If
+     * Restores the state of this WebView from the given Bundle. This method is
+     * intended for use in {@link android.app.Activity#onRestoreInstanceState}
+     * and should be called to restore the state of this WebView. If
      * it is called after this WebView has had a chance to build state (load
      * pages, create a back/forward list, etc.) there may be undesirable
      * side-effects. Please note that this method no longer restores the
@@ -986,13 +996,18 @@
     }
 
     /**
-     * Gets a new picture that captures the current display of this WebView.
-     * This is a copy of the display, and will be unaffected if this WebView
-     * later loads a different URL.
+     * Gets a new picture that captures the current contents of this WebView.
+     * The picture is of the entire document being displayed, and is not
+     * limited to the area currently displayed by this WebView. Also, the
+     * picture is a static copy and is unaffected by later changes to the
+     * content being displayed.
+     * <p>
+     * Note that due to internal changes, for API levels between
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and
+     * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} inclusive, the
+     * picture does not include fixed position elements or scrollable divs.
      *
-     * @return a picture containing the current contents of this WebView. Note
-     *         this picture is of the entire document, and is not restricted to
-     *         the bounds of the view.
+     * @return a picture that captures the current contents of this WebView
      */
     public Picture capturePicture() {
         checkThread();
@@ -1004,6 +1019,7 @@
      *
      * @return the current scale
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public float getScale() {
         checkThread();
         return mProvider.getScale();
@@ -1094,6 +1110,7 @@
      *
      * @return the URL for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getUrl() {
         checkThread();
         return mProvider.getUrl();
@@ -1108,6 +1125,7 @@
      *
      * @return the URL that was originally requested for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getOriginalUrl() {
         checkThread();
         return mProvider.getOriginalUrl();
@@ -1119,6 +1137,7 @@
      *
      * @return the title for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getTitle() {
         checkThread();
         return mProvider.getTitle();
@@ -1161,6 +1180,7 @@
      *
      * @return the height of the HTML content
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public int getContentHeight() {
         checkThread();
         return mProvider.getContentHeight();
@@ -1172,6 +1192,7 @@
      * @return the width of the HTML content
      * @hide
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public int getContentWidth() {
         return mProvider.getContentWidth();
     }
@@ -1246,8 +1267,10 @@
     }
 
     /**
-     * Makes sure that clearing the form data removes the adapter from the
-     * currently focused textfield if there is one.
+     * Removes the autocomplete popup from the currently focused form field, if
+     * present. Note this only affects the display of the autocomplete popup,
+     * it does not remove any saved form data from this WebView's store. To do
+     * that, use {@link WebViewDatabase#clearFormData}.
      */
     public void clearFormData() {
         checkThread();
@@ -1543,7 +1566,6 @@
     @Deprecated
     public void emulateShiftHeld() {
         checkThread();
-        mProvider.emulateShiftHeld();
     }
 
     /**
@@ -1649,7 +1671,24 @@
     @Deprecated
     public void debugDump() {
         checkThread();
-        mProvider.debugDump();
+    }
+
+    /**
+     * See {@link ViewDebug.HierarchyHandler#dumpViewHierarchyWithProperties(BufferedWriter, int)}
+     * @hide
+     */
+    @Override
+    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+        mProvider.dumpViewHierarchyWithProperties(out, level);
+    }
+
+    /**
+     * See {@link ViewDebug.HierarchyHandler#findHierarchyView(String, int)}
+     * @hide
+     */
+    @Override
+    public View findHierarchyView(String className, int hashCode) {
+        return mProvider.findHierarchyView(className, hashCode);
     }
 
     //-------------------------------------------------------------------------
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 84a6129..bef6db9 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -117,6 +117,8 @@
 
 import junit.framework.Assert;
 
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -132,6 +134,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -679,6 +682,8 @@
     // after resize.
     static private final int EDIT_RECT_BUFFER = 10;
 
+    static private final long SELECTION_HANDLE_ANIMATION_MS = 150;
+
     // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
     private boolean mAutoRedraw;
 
@@ -738,12 +743,12 @@
             // the existing GL resources for the html5 video will be destroyed
             // at native side.
             // Here we just need to clean up the Surface Texture which is static.
-            if (level >= TRIM_MEMORY_UI_HIDDEN) {
+            if (level > TRIM_MEMORY_UI_HIDDEN) {
                 HTML5VideoInline.cleanupSurfaceTexture();
+                HTML5VideoView.release();
             }
             WebViewClassic.nativeOnTrimMemory(level);
         }
-
     }
 
     // A final CallbackProxy shared by WebViewCore and BrowserFrame.
@@ -945,21 +950,20 @@
     private Drawable mSelectHandleLeft;
     private Drawable mSelectHandleRight;
     private Drawable mSelectHandleCenter;
-    private Point mSelectHandleLeftOffset;
-    private Point mSelectHandleRightOffset;
-    private Point mSelectHandleCenterOffset;
-    private Point mSelectCursorLeft = new Point();
-    private int mSelectCursorLeftLayerId;
-    private QuadF mSelectCursorLeftTextQuad = new QuadF();
-    private Point mSelectCursorRight = new Point();
-    private int mSelectCursorRightLayerId;
-    private QuadF mSelectCursorRightTextQuad = new QuadF();
+    private Point mSelectOffset;
+    private Point mSelectCursorBase = new Point();
+    private Rect mSelectHandleBaseBounds = new Rect();
+    private int mSelectCursorBaseLayerId;
+    private QuadF mSelectCursorBaseTextQuad = new QuadF();
+    private Point mSelectCursorExtent = new Point();
+    private Rect mSelectHandleExtentBounds = new Rect();
+    private int mSelectCursorExtentLayerId;
+    private QuadF mSelectCursorExtentTextQuad = new QuadF();
     private Point mSelectDraggingCursor;
-    private Point mSelectDraggingOffset;
     private QuadF mSelectDraggingTextQuad;
     private boolean mIsCaretSelection;
-    static final int HANDLE_ID_LEFT = 0;
-    static final int HANDLE_ID_RIGHT = 1;
+    static final int HANDLE_ID_BASE = 0;
+    static final int HANDLE_ID_EXTENT = 1;
 
     // the color used to highlight the touch rectangles
     static final int HIGHLIGHT_COLOR = 0x6633b5e5;
@@ -1033,7 +1037,6 @@
     static final int AUTOFILL_COMPLETE                  = 134;
 
     static final int SCREEN_ON                          = 136;
-    static final int ENTER_FULLSCREEN_VIDEO             = 137;
     static final int UPDATE_ZOOM_DENSITY                = 139;
     static final int EXIT_FULLSCREEN_VIDEO              = 140;
 
@@ -1049,6 +1052,7 @@
     static final int EDIT_TEXT_SIZE_CHANGED             = 150;
     static final int SHOW_CARET_HANDLE                  = 151;
     static final int UPDATE_CONTENT_BOUNDS              = 152;
+    static final int SCROLL_HANDLE_INTO_VIEW            = 153;
 
     private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
     private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
@@ -2196,7 +2200,7 @@
         }
         // We grab a copy of the back/forward list because a client of WebView
         // may have invalidated the history list by calling clearHistory.
-        WebBackForwardList list = copyBackForwardList();
+        WebBackForwardListClassic list = copyBackForwardList();
         final int currentIndex = list.getCurrentIndex();
         final int size = list.getSize();
         // We should fail saving the state if the list is empty or the index is
@@ -2210,7 +2214,7 @@
         // arrays.
         ArrayList<byte[]> history = new ArrayList<byte[]>(size);
         for (int i = 0; i < size; i++) {
-            WebHistoryItem item = list.getItemAtIndex(i);
+            WebHistoryItemClassic item = list.getItemAtIndex(i);
             if (null == item) {
                 // FIXME: this shouldn't happen
                 // need to determine how item got set to null
@@ -2409,7 +2413,7 @@
      */
     @Override
     public WebBackForwardList restoreState(Bundle inState) {
-        WebBackForwardList returnList = null;
+        WebBackForwardListClassic returnList = null;
         if (inState == null) {
             return returnList;
         }
@@ -2417,7 +2421,7 @@
             mCertificate = SslCertificate.restoreState(
                 inState.getBundle("certificate"));
 
-            final WebBackForwardList list = mCallbackProxy.getBackForwardList();
+            final WebBackForwardListClassic list = mCallbackProxy.getBackForwardList();
             final int index = inState.getInt("index");
             // We can't use a clone of the list because we need to modify the
             // shared copy, so synchronize instead to prevent concurrent
@@ -2438,7 +2442,7 @@
                         // the item and thus our history list cannot be rebuilt.
                         return null;
                     }
-                    WebHistoryItem item = new WebHistoryItem(data);
+                    WebHistoryItem item = new WebHistoryItemClassic(data);
                     list.addHistoryItem(item);
                 }
                 // Grab the most recent copy to return to the caller.
@@ -2611,7 +2615,7 @@
      */
     @Override
     public boolean canGoBack() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2634,7 +2638,7 @@
      */
     @Override
     public boolean canGoForward() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2657,7 +2661,7 @@
      */
     @Override
     public boolean canGoBackOrForward(int steps) {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -3305,6 +3309,7 @@
         }
         if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
             scrollLayerTo(scrollX, scrollY);
+            animateHandles();
             return;
         }
         mInOverScrollMode = false;
@@ -3325,6 +3330,8 @@
 
         mWebViewPrivate.super_scrollTo(scrollX, scrollY);
 
+        animateHandles();
+
         if (mOverScrollGlow != null) {
             mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY);
         }
@@ -3371,7 +3378,7 @@
      */
     @Override
     public String getTouchIconUrl() {
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        WebHistoryItemClassic h = mCallbackProxy.getBackForwardList().getCurrentItem();
         return h != null ? h.getTouchIconUrl() : null;
     }
 
@@ -3535,7 +3542,7 @@
      * See {@link WebView#copyBackForwardList()}
      */
     @Override
-    public WebBackForwardList copyBackForwardList() {
+    public WebBackForwardListClassic copyBackForwardList() {
         return mCallbackProxy.getBackForwardList().clone();
     }
 
@@ -3543,7 +3550,8 @@
      * See {@link WebView#setFindListener(WebView.FindListener)}.
      * @hide
      */
-     public void setFindListener(WebView.FindListener listener) {
+     @Override
+    public void setFindListener(WebView.FindListener listener) {
          mFindListener = listener;
      }
 
@@ -3566,6 +3574,7 @@
         return findAllBody(find, false);
     }
 
+    @Override
     public void findAllAsync(String find) {
         findAllBody(find, true);
     }
@@ -3604,6 +3613,7 @@
      *             If false and text is non-null, perform a find all.
      * @return boolean True if the find dialog is shown, false otherwise.
      */
+    @Override
     public boolean showFindDialog(String text, boolean showIme) {
         FindActionModeCallback callback = new FindActionModeCallback(mContext);
         if (mWebView.getParent() == null || mWebView.startActionMode(callback) == null) {
@@ -3819,17 +3829,14 @@
             return;
         }
         if (mSelectingText) {
-            if (mSelectCursorLeftLayerId == mCurrentScrollingLayerId) {
-                mSelectCursorLeft.offset(dx, dy);
-                mSelectCursorLeftTextQuad.offset(dx, dy);
+            if (mSelectCursorBaseLayerId == mCurrentScrollingLayerId) {
+                mSelectCursorBase.offset(dx, dy);
+                mSelectCursorBaseTextQuad.offset(dx, dy);
             }
-            if (mSelectCursorRightLayerId == mCurrentScrollingLayerId) {
-                mSelectCursorRight.offset(dx, dy);
-                mSelectCursorRightTextQuad.offset(dx, dy);
+            if (mSelectCursorExtentLayerId == mCurrentScrollingLayerId) {
+                mSelectCursorExtent.offset(dx, dy);
+                mSelectCursorExtentTextQuad.offset(dx, dy);
             }
-        } else if (mHandleAlpha.getAlpha() > 0) {
-            // stop fading as we're not going to move with the layer.
-            mHandleAlphaAnimator.end();
         }
         if (mAutoCompletePopup != null &&
                 mCurrentScrollingLayerId == mEditTextLayerId) {
@@ -4445,9 +4452,6 @@
     }
 
     private void onZoomAnimationStart() {
-        if (!mSelectingText && mHandleAlpha.getAlpha() > 0) {
-            mHandleAlphaAnimator.end();
-        }
     }
 
     private void onZoomAnimationEnd() {
@@ -4480,34 +4484,63 @@
 
     private class SelectionHandleAlpha {
         private int mAlpha = 0;
+        private int mTargetAlpha = 0;
+
         public void setAlpha(int alpha) {
             mAlpha = alpha;
-            if (mSelectHandleCenter != null) {
-                mSelectHandleCenter.setAlpha(alpha);
-                mSelectHandleLeft.setAlpha(alpha);
-                mSelectHandleRight.setAlpha(alpha);
-                // TODO: Use partial invalidate
-                invalidate();
-            }
+            // TODO: Use partial invalidate
+            invalidate();
         }
 
         public int getAlpha() {
             return mAlpha;
         }
 
+        public void setTargetAlpha(int alpha) {
+            mTargetAlpha = alpha;
+        }
+
+        public int getTargetAlpha() {
+            return mTargetAlpha;
+        }
+
     }
 
     private void startSelectingText() {
         mSelectingText = true;
         mShowTextSelectionExtra = true;
-        mHandleAlphaAnimator.setIntValues(255);
-        mHandleAlphaAnimator.start();
+        animateHandles();
     }
+
+    private void animateHandle(boolean canShow, ObjectAnimator animator,
+            Point selectionPoint, int selectionLayerId,
+            SelectionHandleAlpha alpha) {
+        boolean isVisible = canShow && mSelectingText
+                && ((mSelectionStarted && mSelectDraggingCursor == selectionPoint)
+                || isHandleVisible(selectionPoint, selectionLayerId));
+        int targetValue = isVisible ? 255 : 0;
+        if (targetValue != alpha.getTargetAlpha()) {
+            alpha.setTargetAlpha(targetValue);
+            animator.setIntValues(targetValue);
+            animator.setDuration(SELECTION_HANDLE_ANIMATION_MS);
+            animator.start();
+        }
+    }
+
+    private void animateHandles() {
+        boolean canShowBase = mSelectingText;
+        boolean canShowExtent = mSelectingText && !mIsCaretSelection;
+        animateHandle(canShowBase, mBaseHandleAlphaAnimator, mSelectCursorBase,
+                mSelectCursorBaseLayerId, mBaseAlpha);
+        animateHandle(canShowExtent, mExtentHandleAlphaAnimator,
+                mSelectCursorExtent, mSelectCursorExtentLayerId,
+                mExtentAlpha);
+    }
+
     private void endSelectingText() {
         mSelectingText = false;
         mShowTextSelectionExtra = false;
-        mHandleAlphaAnimator.setIntValues(0);
-        mHandleAlphaAnimator.start();
+        animateHandles();
     }
 
     private void ensureSelectionHandles() {
@@ -4518,66 +4551,87 @@
                     com.android.internal.R.drawable.text_select_handle_left);
             mSelectHandleRight = mContext.getResources().getDrawable(
                     com.android.internal.R.drawable.text_select_handle_right);
-            mHandleAlpha.setAlpha(mHandleAlpha.getAlpha());
-            mSelectHandleCenterOffset = new Point(0,
-                    -mSelectHandleCenter.getIntrinsicHeight());
-            mSelectHandleLeftOffset = new Point(0,
+            // All handles have the same height, so we can save effort with
+            // this assumption.
+            mSelectOffset = new Point(0,
                     -mSelectHandleLeft.getIntrinsicHeight());
-            mSelectHandleRightOffset = new Point(
-                    -mSelectHandleLeft.getIntrinsicWidth() / 2,
-                    -mSelectHandleRight.getIntrinsicHeight());
         }
     }
 
+    private void drawHandle(Point point, int handleId, Rect bounds,
+            int alpha, Canvas canvas) {
+        int offset;
+        int width;
+        int height;
+        Drawable drawable;
+        boolean isLeft = nativeIsHandleLeft(mNativeClass, handleId);
+        if (isLeft) {
+            drawable = mSelectHandleLeft;
+            width = mSelectHandleLeft.getIntrinsicWidth();
+            height = mSelectHandleLeft.getIntrinsicHeight();
+            // Magic formula copied from TextView
+            offset = (width * 3) / 4;
+        } else {
+            drawable = mSelectHandleRight;
+            width = mSelectHandleRight.getIntrinsicWidth();
+            height = mSelectHandleRight.getIntrinsicHeight();
+            // Magic formula copied from TextView
+            offset = width / 4;
+        }
+        int x = contentToViewDimension(point.x);
+        int y = contentToViewDimension(point.y);
+        bounds.set(x - offset, y, x - offset + width, y + height);
+        drawable.setBounds(bounds);
+        drawable.setAlpha(alpha);
+        drawable.draw(canvas);
+    }
+
     private void drawTextSelectionHandles(Canvas canvas) {
-        if (mHandleAlpha.getAlpha() == 0) {
+        if (mBaseAlpha.getAlpha() == 0 && mExtentAlpha.getAlpha() == 0) {
             return;
         }
         ensureSelectionHandles();
-        if (mSelectingText) {
-            int[] handles = new int[4];
-            getSelectionHandles(handles);
-            int start_x = contentToViewDimension(handles[0]);
-            int start_y = contentToViewDimension(handles[1]);
-            int end_x = contentToViewDimension(handles[2]);
-            int end_y = contentToViewDimension(handles[3]);
-
-            if (mIsCaretSelection) {
-                // Caret handle is centered
-                start_x -= (mSelectHandleCenter.getIntrinsicWidth() / 2);
-                mSelectHandleCenter.setBounds(start_x, start_y,
-                        start_x + mSelectHandleCenter.getIntrinsicWidth(),
-                        start_y + mSelectHandleCenter.getIntrinsicHeight());
-            } else {
-                // Magic formula copied from TextView
-                start_x -= (mSelectHandleLeft.getIntrinsicWidth() * 3) / 4;
-                mSelectHandleLeft.setBounds(start_x, start_y,
-                        start_x + mSelectHandleLeft.getIntrinsicWidth(),
-                        start_y + mSelectHandleLeft.getIntrinsicHeight());
-                end_x -= mSelectHandleRight.getIntrinsicWidth() / 4;
-                mSelectHandleRight.setBounds(end_x, end_y,
-                        end_x + mSelectHandleRight.getIntrinsicWidth(),
-                        end_y + mSelectHandleRight.getIntrinsicHeight());
-            }
-        }
-
         if (mIsCaretSelection) {
+            // Caret handle is centered
+            int x = contentToViewDimension(mSelectCursorBase.x) -
+                    (mSelectHandleCenter.getIntrinsicWidth() / 2);
+            int y = contentToViewDimension(mSelectCursorBase.y);
+            mSelectHandleBaseBounds.set(x, y,
+                    x + mSelectHandleCenter.getIntrinsicWidth(),
+                    y + mSelectHandleCenter.getIntrinsicHeight());
+            mSelectHandleCenter.setBounds(mSelectHandleBaseBounds);
+            mSelectHandleCenter.setAlpha(mBaseAlpha.getAlpha());
             mSelectHandleCenter.draw(canvas);
         } else {
-            mSelectHandleLeft.draw(canvas);
-            mSelectHandleRight.draw(canvas);
+            drawHandle(mSelectCursorBase, HANDLE_ID_BASE,
+                    mSelectHandleBaseBounds, mBaseAlpha.getAlpha(), canvas);
+            drawHandle(mSelectCursorExtent, HANDLE_ID_EXTENT,
+                    mSelectHandleExtentBounds, mExtentAlpha.getAlpha(), canvas);
         }
     }
 
+    private boolean isHandleVisible(Point selectionPoint, int layerId) {
+        boolean isVisible = true;
+        if (mIsEditingText) {
+            isVisible = mEditTextContentBounds.contains(selectionPoint.x,
+                    selectionPoint.y);
+        }
+        if (isVisible) {
+            isVisible = nativeIsPointVisible(mNativeClass, layerId,
+                    selectionPoint.x, selectionPoint.y);
+        }
+        return isVisible;
+    }
+
     /**
      * Takes an int[4] array as an output param with the values being
      * startX, startY, endX, endY
      */
     private void getSelectionHandles(int[] handles) {
-        handles[0] = mSelectCursorLeft.x;
-        handles[1] = mSelectCursorLeft.y;
-        handles[2] = mSelectCursorRight.x;
-        handles[3] = mSelectCursorRight.y;
+        handles[0] = mSelectCursorBase.x;
+        handles[1] = mSelectCursorBase.y;
+        handles[2] = mSelectCursorExtent.x;
+        handles[3] = mSelectCursorExtent.y;
     }
 
     // draw history
@@ -4812,6 +4866,43 @@
     }
 
     /**
+     * Sets use of the Geolocation mock client. Also resets that client. Called
+     * by DRT on UI thread, need to proxy to WebCore thread.
+     *
+     * debug only
+     */
+    public void setUseMockGeolocation() {
+        mWebViewCore.sendMessage(EventHub.SET_USE_MOCK_GEOLOCATION);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * debug only
+     */
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        mWebViewCore.setMockGeolocationPosition(latitude, longitude, accuracy);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * debug only
+     */
+    public void setMockGeolocationError(int code, String message) {
+        mWebViewCore.setMockGeolocationError(code, message);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * debug only
+     */
+    public void setMockGeolocationPermission(boolean allow) {
+        mWebViewCore.setMockGeolocationPermission(allow);
+    }
+
+    /**
      * Called by DRT on WebCore thread.
      *
      * debug only
@@ -5044,8 +5135,8 @@
         ClipboardManager cm = (ClipboardManager)(mContext
                 .getSystemService(Context.CLIPBOARD_SERVICE));
         if (cm.hasPrimaryClip()) {
-            Point cursorPoint = new Point(contentToViewX(mSelectCursorLeft.x),
-                    contentToViewY(mSelectCursorLeft.y));
+            Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x),
+                    contentToViewY(mSelectCursorBase.y));
             Point cursorTop = calculateCaretTop();
             cursorTop.set(contentToViewX(cursorTop.x),
                     contentToViewY(cursorTop.y));
@@ -5095,12 +5186,12 @@
      * calculates the top of a caret.
      */
     private Point calculateCaretTop() {
-        float scale = scaleAlongSegment(mSelectCursorLeft.x, mSelectCursorLeft.y,
-                mSelectCursorLeftTextQuad.p4, mSelectCursorLeftTextQuad.p3);
+        float scale = scaleAlongSegment(mSelectCursorBase.x, mSelectCursorBase.y,
+                mSelectCursorBaseTextQuad.p4, mSelectCursorBaseTextQuad.p3);
         int x = Math.round(scaleCoordinate(scale,
-                mSelectCursorLeftTextQuad.p1.x, mSelectCursorLeftTextQuad.p2.x));
+                mSelectCursorBaseTextQuad.p1.x, mSelectCursorBaseTextQuad.p2.x));
         int y = Math.round(scaleCoordinate(scale,
-                mSelectCursorLeftTextQuad.p1.y, mSelectCursorLeftTextQuad.p2.y));
+                mSelectCursorBaseTextQuad.p1.y, mSelectCursorBaseTextQuad.p2.y));
         return new Point(x, y);
     }
 
@@ -5111,50 +5202,12 @@
     }
 
     private void syncSelectionCursors() {
-        mSelectCursorLeftLayerId =
-                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_LEFT,
-                        mSelectCursorLeft, mSelectCursorLeftTextQuad);
-        mSelectCursorRightLayerId =
-                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_RIGHT,
-                        mSelectCursorRight, mSelectCursorRightTextQuad);
-    }
-
-    private void adjustSelectionCursors() {
-        if (mIsCaretSelection) {
-            syncSelectionCursors();
-            return; // no need to swap left and right handles.
-        }
-
-        boolean wasDraggingLeft = (mSelectDraggingCursor == mSelectCursorLeft);
-        int oldX = mSelectDraggingCursor.x;
-        int oldY = mSelectDraggingCursor.y;
-        int oldLeftX = mSelectCursorLeft.x;
-        int oldLeftY = mSelectCursorLeft.y;
-        int oldRightX = mSelectCursorRight.x;
-        int oldRightY = mSelectCursorRight.y;
-        syncSelectionCursors();
-
-        boolean rightChanged = (oldRightX != mSelectCursorRight.x
-                || oldRightY != mSelectCursorRight.y);
-        boolean leftChanged = (oldLeftX != mSelectCursorLeft.x
-                || oldLeftY != mSelectCursorLeft.y);
-        if (leftChanged && rightChanged) {
-            // Left and right switched places, so swap dragging cursor
-            boolean draggingLeft = !wasDraggingLeft;
-            mSelectDraggingCursor = (draggingLeft
-                    ? mSelectCursorLeft : mSelectCursorRight);
-            mSelectDraggingTextQuad = (draggingLeft
-                    ? mSelectCursorLeftTextQuad : mSelectCursorRightTextQuad);
-            mSelectDraggingOffset = (draggingLeft
-                    ? mSelectHandleLeftOffset : mSelectHandleRightOffset);
-        }
-        mSelectDraggingCursor.set(oldX, oldY);
-    }
-
-    private float distanceSquared(int x, int y, Point p) {
-        float dx = p.x - x;
-        float dy = p.y - y;
-        return (dx * dx) + (dy * dy);
+        mSelectCursorBaseLayerId =
+                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE,
+                        mSelectCursorBase, mSelectCursorBaseTextQuad);
+        mSelectCursorExtentLayerId =
+                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_EXTENT,
+                        mSelectCursorExtent, mSelectCursorExtentTextQuad);
     }
 
     private boolean setupWebkitSelect() {
@@ -5169,18 +5222,11 @@
     }
 
     private void updateWebkitSelection() {
-        int[] handles = null;
-        if (mIsCaretSelection) {
-            mSelectCursorRight.set(mSelectCursorLeft.x, mSelectCursorLeft.y);
-        }
-        if (mSelectingText) {
-            handles = new int[4];
-            getSelectionHandles(handles);
-        } else {
-            nativeSetTextSelection(mNativeClass, 0);
-        }
+        int handleId = (mSelectDraggingCursor == mSelectCursorBase)
+                ? HANDLE_ID_BASE : HANDLE_ID_EXTENT;
         mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
-        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, handles);
+        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT,
+                mSelectDraggingCursor.x, mSelectDraggingCursor.y, (Integer)handleId);
     }
 
     private void resetCaretTimer() {
@@ -5192,14 +5238,6 @@
     }
 
     /**
-     * See {@link WebView#emulateShiftHeld()}
-     */
-    @Override
-    @Deprecated
-    public void emulateShiftHeld() {
-    }
-
-    /**
      * Select all of the text in this WebView.
      *
      * This is an implementation detail.
@@ -5543,21 +5581,21 @@
         Point caretTop = calculateCaretTop();
         if (visibleRect.width() < mEditTextContentBounds.width()) {
             // The whole edit won't fit in the width, so use the caret rect
-            if (mSelectCursorLeft.x < caretTop.x) {
-                showRect.left = Math.max(0, mSelectCursorLeft.x - buffer);
+            if (mSelectCursorBase.x < caretTop.x) {
+                showRect.left = Math.max(0, mSelectCursorBase.x - buffer);
                 showRect.right = caretTop.x + buffer;
             } else {
                 showRect.left = Math.max(0, caretTop.x - buffer);
-                showRect.right = mSelectCursorLeft.x + buffer;
+                showRect.right = mSelectCursorBase.x + buffer;
             }
         }
         if (visibleRect.height() < mEditTextContentBounds.height()) {
             // The whole edit won't fit in the height, so use the caret rect
-            if (mSelectCursorLeft.y > caretTop.y) {
+            if (mSelectCursorBase.y > caretTop.y) {
                 showRect.top = Math.max(0, caretTop.y - buffer);
-                showRect.bottom = mSelectCursorLeft.y + buffer;
+                showRect.bottom = mSelectCursorBase.y + buffer;
             } else {
-                showRect.top = Math.max(0, mSelectCursorLeft.y - buffer);
+                showRect.top = Math.max(0, mSelectCursorBase.y - buffer);
                 showRect.bottom = caretTop.y + buffer;
             }
         }
@@ -5801,28 +5839,19 @@
                         ensureSelectionHandles();
                         int shiftedY = y - getTitleHeight() + getScrollY();
                         int shiftedX = x + getScrollX();
-                        if (mSelectHandleCenter != null && mSelectHandleCenter.getBounds()
+                        if (mSelectHandleBaseBounds.contains(shiftedX, shiftedY)) {
+                            mSelectionStarted = true;
+                            mSelectDraggingCursor = mSelectCursorBase;
+                            mSelectDraggingTextQuad = mSelectCursorBaseTextQuad;
+                            if (mIsCaretSelection) {
+                                mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
+                                hidePasteButton();
+                            }
+                        } else if (mSelectHandleExtentBounds
                                 .contains(shiftedX, shiftedY)) {
                             mSelectionStarted = true;
-                            mSelectDraggingCursor = mSelectCursorLeft;
-                            mSelectDraggingOffset = mSelectHandleCenterOffset;
-                            mSelectDraggingTextQuad = mSelectCursorLeftTextQuad;
-                            mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
-                            hidePasteButton();
-                        } else if (mSelectHandleLeft != null
-                                && mSelectHandleLeft.getBounds()
-                                    .contains(shiftedX, shiftedY)) {
-                            mSelectionStarted = true;
-                            mSelectDraggingOffset = mSelectHandleLeftOffset;
-                            mSelectDraggingCursor = mSelectCursorLeft;
-                            mSelectDraggingTextQuad = mSelectCursorLeftTextQuad;
-                        } else if (mSelectHandleRight != null
-                                && mSelectHandleRight.getBounds()
-                                .contains(shiftedX, shiftedY)) {
-                            mSelectionStarted = true;
-                            mSelectDraggingOffset = mSelectHandleRightOffset;
-                            mSelectDraggingCursor = mSelectCursorRight;
-                            mSelectDraggingTextQuad = mSelectCursorRightTextQuad;
+                            mSelectDraggingCursor = mSelectCursorExtent;
+                            mSelectDraggingTextQuad = mSelectCursorExtentTextQuad;
                         } else if (mIsCaretSelection) {
                             selectionDone();
                         }
@@ -5867,9 +5896,9 @@
                     }
                     if (deltaX != 0 || deltaY != 0) {
                         int handleX = contentX +
-                                viewToContentDimension(mSelectDraggingOffset.x);
+                                viewToContentDimension(mSelectOffset.x);
                         int handleY = contentY +
-                                viewToContentDimension(mSelectDraggingOffset.y);
+                                viewToContentDimension(mSelectOffset.y);
                         mSelectDraggingCursor.set(handleX, handleY);
                         boolean inCursorText =
                                 mSelectDraggingTextQuad.containsPoint(handleX, handleY);
@@ -6006,12 +6035,15 @@
                 break;
             }
             case MotionEvent.ACTION_UP: {
-                endScrollEdit();
-                if (!mConfirmMove && mIsEditingText && mSelectionStarted &&
-                        mIsCaretSelection) {
-                    showPasteWindow();
-                    stopTouch();
-                    break;
+                if (mIsEditingText && mSelectionStarted) {
+                    endScrollEdit();
+                    mPrivateHandler.sendEmptyMessageDelayed(SCROLL_HANDLE_INTO_VIEW,
+                            TEXT_SCROLL_FIRST_SCROLL_MS);
+                    if (!mConfirmMove && mIsCaretSelection) {
+                        showPasteWindow();
+                        stopTouch();
+                        break;
+                    }
                 }
                 mLastTouchUpTime = eventTime;
                 if (mSentAutoScrollMessage) {
@@ -6118,6 +6150,10 @@
         }
     }
 
+    private static int getSelectionCoordinate(int coordinate, int min, int max) {
+        return Math.max(Math.min(coordinate, max), min);
+    }
+
     private void beginScrollEdit() {
         if (mLastEditScroll == 0) {
             mLastEditScroll = SystemClock.uptimeMillis() -
@@ -6126,10 +6162,37 @@
         }
     }
 
+    private void scrollDraggedSelectionHandleIntoView() {
+        if (mSelectDraggingCursor == null) {
+            return;
+        }
+        int x = mSelectDraggingCursor.x;
+        int y = mSelectDraggingCursor.y;
+        if (!mEditTextContentBounds.contains(x,y)) {
+            int left = Math.min(0, x - mEditTextContentBounds.left - EDIT_RECT_BUFFER);
+            int right = Math.max(0, x - mEditTextContentBounds.right + EDIT_RECT_BUFFER);
+            int deltaX = left + right;
+            int above = Math.min(0, y - mEditTextContentBounds.top - EDIT_RECT_BUFFER);
+            int below = Math.max(0, y - mEditTextContentBounds.bottom + EDIT_RECT_BUFFER);
+            int deltaY = above + below;
+            if (deltaX != 0 || deltaY != 0) {
+                int scrollX = getTextScrollX() + deltaX;
+                int scrollY = getTextScrollY() + deltaY;
+                scrollX = clampBetween(scrollX, 0, getMaxTextScrollX());
+                scrollY = clampBetween(scrollY, 0, getMaxTextScrollY());
+                scrollEditText(scrollX, scrollY);
+            }
+        }
+    }
+
     private void endScrollEdit() {
         mLastEditScroll = 0;
     }
 
+    private static int clampBetween(int value, int min, int max) {
+        return Math.max(min, Math.min(value, max));
+    }
+
     private static int getTextScrollDelta(float speed, long deltaT) {
         float distance = speed * deltaT;
         int intDistance = (int)Math.floor(distance);
@@ -6145,10 +6208,10 @@
      */
     private void scrollEditWithCursor() {
         if (mLastEditScroll != 0) {
-            int x = viewToContentX(mLastTouchX + getScrollX() + mSelectDraggingOffset.x);
+            int x = viewToContentX(mLastTouchX + getScrollX() + mSelectOffset.x);
             float scrollSpeedX = getTextScrollSpeed(x, mEditTextContentBounds.left,
                     mEditTextContentBounds.right);
-            int y = viewToContentY(mLastTouchY + getScrollY() + mSelectDraggingOffset.y);
+            int y = viewToContentY(mLastTouchY + getScrollY() + mSelectOffset.y);
             float scrollSpeedY = getTextScrollSpeed(y, mEditTextContentBounds.top,
                     mEditTextContentBounds.bottom);
             if (scrollSpeedX == 0.0f && scrollSpeedY == 0.0f) {
@@ -6158,24 +6221,27 @@
                 long timeSinceLastUpdate = currentTime - mLastEditScroll;
                 int deltaX = getTextScrollDelta(scrollSpeedX, timeSinceLastUpdate);
                 int deltaY = getTextScrollDelta(scrollSpeedY, timeSinceLastUpdate);
+                int scrollX = getTextScrollX() + deltaX;
+                scrollX = clampBetween(scrollX, 0, getMaxTextScrollX());
+                int scrollY = getTextScrollY() + deltaY;
+                scrollY = clampBetween(scrollY, 0, getMaxTextScrollY());
+
                 mLastEditScroll = currentTime;
-                if (deltaX == 0 && deltaY == 0) {
+                if (scrollX == getTextScrollX() && scrollY == getTextScrollY()) {
                     // By probability no text scroll this time. Try again later.
                     mPrivateHandler.sendEmptyMessageDelayed(SCROLL_EDIT_TEXT,
                             TEXT_SCROLL_FIRST_SCROLL_MS);
                 } else {
-                    int scrollX = getTextScrollX() + deltaX;
-                    scrollX = Math.min(getMaxTextScrollX(), scrollX);
-                    scrollX = Math.max(0, scrollX);
-                    int scrollY = getTextScrollY() + deltaY;
-                    scrollY = Math.min(getMaxTextScrollY(), scrollY);
-                    scrollY = Math.max(0, scrollY);
-                    scrollEditText(scrollX, scrollY);
-                    int cursorX = mSelectDraggingCursor.x;
-                    int cursorY = mSelectDraggingCursor.y;
-                    mSelectDraggingCursor.set(x - deltaX, y - deltaY);
+                    int selectionX = getSelectionCoordinate(x,
+                            mEditTextContentBounds.left, mEditTextContentBounds.right);
+                    int selectionY = getSelectionCoordinate(y,
+                            mEditTextContentBounds.top, mEditTextContentBounds.bottom);
+                    int oldX = mSelectDraggingCursor.x;
+                    int oldY = mSelectDraggingCursor.y;
+                    mSelectDraggingCursor.set(selectionX, selectionY);
                     updateWebkitSelection();
-                    mSelectDraggingCursor.set(cursorX, cursorY);
+                    scrollEditText(scrollX, scrollY);
+                    mSelectDraggingCursor.set(oldX, oldY);
                 }
             }
         }
@@ -6231,10 +6297,10 @@
                 // scrolling.  The rectangle is in document coordinates.
                 final int maxX = mScrollingLayerRect.right;
                 final int maxY = mScrollingLayerRect.bottom;
-                final int resultX = Math.max(0,
-                        Math.min(mScrollingLayerRect.left + contentX, maxX));
-                final int resultY = Math.max(0,
-                        Math.min(mScrollingLayerRect.top + contentY, maxY));
+                final int resultX = clampBetween(maxX, 0,
+                        mScrollingLayerRect.left + contentX);
+                final int resultY = clampBetween(maxY, 0,
+                        mScrollingLayerRect.top + contentY);
 
                 if (resultX != mScrollingLayerRect.left
                         || resultY != mScrollingLayerRect.top
@@ -6335,10 +6401,10 @@
         int x = Math.round(newX);
         int y = Math.round(newY);
         if (mIsEditingText) {
-            x = Math.max(mEditTextContentBounds.left,
-                    Math.min(mEditTextContentBounds.right, x));
-            y = Math.max(mEditTextContentBounds.top,
-                    Math.min(mEditTextContentBounds.bottom, y));
+            x = clampBetween(x, mEditTextContentBounds.left,
+                    mEditTextContentBounds.right);
+            y = clampBetween(y, mEditTextContentBounds.top,
+                    mEditTextContentBounds.bottom);
         }
         mSelectDraggingCursor.set(x, y);
     }
@@ -6401,9 +6467,12 @@
     private long mTrackballUpTime = 0;
     private long mLastCursorTime = 0;
     private Rect mLastCursorBounds;
-    private SelectionHandleAlpha mHandleAlpha = new SelectionHandleAlpha();
-    private ObjectAnimator mHandleAlphaAnimator =
-            ObjectAnimator.ofInt(mHandleAlpha, "alpha", 0);
+    private SelectionHandleAlpha mBaseAlpha = new SelectionHandleAlpha();
+    private SelectionHandleAlpha mExtentAlpha = new SelectionHandleAlpha();
+    private ObjectAnimator mBaseHandleAlphaAnimator =
+            ObjectAnimator.ofInt(mBaseAlpha, "alpha", 0);
+    private ObjectAnimator mExtentHandleAlphaAnimator =
+            ObjectAnimator.ofInt(mExtentAlpha, "alpha", 0);
 
     // Set by default; BrowserActivity clears to interpret trackball data
     // directly for movement. Currently, the framework only passes
@@ -6413,6 +6482,7 @@
     private DrawData mDelaySetPicture;
     private DrawData mLoadedPicture;
 
+    @Override
     public void setMapTrackballToArrowKeys(boolean setMap) {
         mMapTrackballToArrowKeys = setMap;
     }
@@ -6639,6 +6709,7 @@
         }
     }
 
+    @Override
     public void flingScroll(int vx, int vy) {
         mScroller.fling(getScrollX(), getScrollY(), vx, vy, 0, computeMaxScrollX(), 0,
                 computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
@@ -7290,15 +7361,6 @@
                     mWebView.setKeepScreenOn(msg.arg1 == 1);
                     break;
 
-                case ENTER_FULLSCREEN_VIDEO:
-                    int layerId = msg.arg1;
-
-                    String url = (String) msg.obj;
-                    if (mHTML5VideoViewProxy != null) {
-                        mHTML5VideoViewProxy.enterFullScreenVideo(layerId, url);
-                    }
-                    break;
-
                 case EXIT_FULLSCREEN_VIDEO:
                     if (mHTML5VideoViewProxy != null) {
                         mHTML5VideoViewProxy.exitFullScreenVideo();
@@ -7437,7 +7499,7 @@
                         mEditTextLayerId = initData.mNodeLayerId;
                         nativeMapLayerRect(mNativeClass, mEditTextLayerId,
                                 mEditTextContentBounds);
-                        mEditTextContent.set(initData.mContentRect);
+                        mEditTextContent.set(initData.mClientRect);
                         relocateAutoCompletePopup();
                     }
                     break;
@@ -7518,6 +7580,10 @@
                     scrollEditWithCursor();
                     break;
 
+                case SCROLL_HANDLE_INTO_VIEW:
+                    scrollDraggedSelectionHandleIntoView();
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -7553,8 +7619,8 @@
                         .contains(x, y);
             } else {
                 isPressingHandle =
-                        mSelectHandleLeft.getBounds().contains(x, y)
-                        || mSelectHandleRight.getBounds().contains(x, y);
+                        mSelectHandleBaseBounds.contains(x, y)
+                        || mSelectHandleExtentBounds.contains(x, y);
             }
             return isPressingHandle;
         }
@@ -7842,7 +7908,9 @@
         int functor = 0;
         boolean forceInval = isPictureAfterFirstLayout;
         ViewRootImpl viewRoot = mWebView.getViewRootImpl();
-        if (mWebView.isHardwareAccelerated() && viewRoot != null) {
+        if (mWebView.isHardwareAccelerated()
+                && mWebView.getLayerType() != View.LAYER_TYPE_SOFTWARE
+                && viewRoot != null) {
             functor = nativeGetDrawGLFunction(mNativeClass);
             if (functor != 0) {
                 // force an invalidate if functor attach not successful
@@ -7901,8 +7969,10 @@
 
         if (data.mSelectTextPtr != 0 &&
                 (data.mStart != data.mEnd ||
-                (mFieldPointer == nodePointer && mFieldPointer != 0))) {
-            mIsCaretSelection = (data.mStart == data.mEnd);
+                (mFieldPointer == nodePointer && mFieldPointer != 0) ||
+                (nodePointer == 0 && data.mStart == 0 && data.mEnd == 0))) {
+            mIsEditingText = (mFieldPointer == nodePointer) && nodePointer != 0;
+            mIsCaretSelection = (data.mStart == data.mEnd && nodePointer != 0);
             if (mIsCaretSelection &&
                     (mInputConnection == null ||
                     mInputConnection.getEditable().length() == 0)) {
@@ -7911,11 +7981,10 @@
             } else {
                 if (!mSelectingText) {
                     setupWebkitSelect();
-                } else if (!mSelectionStarted) {
-                    syncSelectionCursors();
                 } else {
-                    adjustSelectionCursors();
+                    syncSelectionCursors();
                 }
+                animateHandles();
                 if (mIsCaretSelection) {
                     resetCaretTimer();
                 }
@@ -7931,8 +8000,10 @@
         float maxScrollX = getMaxTextScrollX();
         float scrollPercentX = ((float)scrollX)/maxScrollX;
         mEditTextContent.offsetTo(-scrollX, -scrollY);
-        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SCROLL_TEXT_INPUT, 0,
+        mWebViewCore.removeMessages(EventHub.SCROLL_TEXT_INPUT);
+        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, 0,
                 scrollY, (Float)scrollPercentX);
+        animateHandles();
     }
 
     private void beginTextBatch() {
@@ -8377,14 +8448,6 @@
     }
 
     /**
-     * See {@link WebView#debugDump()}
-     */
-    @Override
-    @Deprecated
-    public void debugDump() {
-    }
-
-    /**
      * Enable the communication b/t the webView and VideoViewProxy
      *
      * only used by the Browser
@@ -8518,6 +8581,54 @@
         WebViewCore.setShouldMonitorWebCoreThread();
     }
 
+    @Override
+    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+        int layer = getBaseLayer();
+        if (layer != 0) {
+            try {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                ViewStateSerializer.dumpLayerHierarchy(layer, stream, level);
+                stream.close();
+                byte[] buf = stream.toByteArray();
+                out.write(new String(buf, "ascii"));
+            } catch (IOException e) {}
+        }
+    }
+
+    @Override
+    public View findHierarchyView(String className, int hashCode) {
+        if (mNativeClass == 0) return null;
+        Picture pic = new Picture();
+        if (!nativeDumpLayerContentToPicture(mNativeClass, className, hashCode, pic)) {
+            return null;
+        }
+        return new PictureWrapperView(getContext(), pic, mWebView);
+    }
+
+    private static class PictureWrapperView extends View {
+        Picture mPicture;
+        WebView mWebView;
+
+        public PictureWrapperView(Context context, Picture picture, WebView parent) {
+            super(context);
+            mPicture = picture;
+            mWebView = parent;
+            setWillNotDraw(false);
+            setRight(mPicture.getWidth());
+            setBottom(mPicture.getHeight());
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            canvas.drawPicture(mPicture);
+        }
+
+        @Override
+        public boolean post(Runnable action) {
+            return mWebView.post(action);
+        }
+    }
+
     private native void     nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
     private native void     nativeDebugDump();
     private static native void nativeDestroy(int ptr);
@@ -8538,6 +8649,8 @@
             int scrollingLayer);
     private native int      nativeGetBaseLayer(int nativeInstance);
     private native void     nativeCopyBaseContentToPicture(Picture pict);
+    private native boolean     nativeDumpLayerContentToPicture(int nativeInstance,
+            String className, int layerId, Picture pict);
     private native boolean  nativeHasContent();
     private native void     nativeStopGL(int ptr);
     private native void     nativeDiscardAllTextures();
@@ -8581,4 +8694,7 @@
     private static native int nativeSetHwAccelerated(int instance, boolean hwAccelerated);
     private static native void nativeFindMaxVisibleRect(int instance, int layerId,
             Rect visibleContentRect);
+    private static native boolean nativeIsHandleLeft(int instance, int handleId);
+    private static native boolean nativeIsPointVisible(int instance,
+            int layerId, int contentX, int contentY);
 }
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 6aff10a..08a046a 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -204,43 +204,16 @@
     }
 
     /**
-     * Notify the host application that an SSL error occurred while loading a
-     * resource, but the WebView chose to proceed anyway based on a
-     * decision retained from a previous response to onReceivedSslError().
-     * @hide
-     */
-    public void onProceededAfterSslError(WebView view, SslError error) {
-    }
-
-    /**
-     * Notify the host application to handle a SSL client certificate
-     * request (display the request to the user and ask whether to
-     * proceed with a client certificate or not). The host application
-     * has to call either handler.cancel() or handler.proceed() as the
-     * connection is suspended and waiting for the response. The
-     * default behavior is to cancel, returning no client certificate.
+     * Notifies the host application that the WebView received an HTTP
+     * authentication request. The host application can use the supplied
+     * {@link HttpAuthHandler} to set the WebView's response to the request.
+     * The default behavior is to cancel the request.
      *
-     * @param view The WebView that is initiating the callback.
-     * @param handler A ClientCertRequestHandler object that will
-     *            handle the user's response.
-     * @param host_and_port The host and port of the requesting server.
-     *
-     * @hide
-     */
-    public void onReceivedClientCertRequest(WebView view,
-            ClientCertRequestHandler handler, String host_and_port) {
-        handler.cancel();
-    }
-
-    /**
-     * Notify the host application to handle an authentication request. The
-     * default behavior is to cancel the request.
-     *
-     * @param view The WebView that is initiating the callback.
-     * @param handler The HttpAuthHandler that will handle the user's response.
-     * @param host The host requiring authentication.
-     * @param realm A description to help store user credentials for future
-     *            visits.
+     * @param view the WebView that is initiating the callback
+     * @param handler the HttpAuthHandler used to set the WebView's response
+     * @param host the host requiring authentication
+     * @param realm the realm for which authentication is required
+     * @see Webview#getHttpAuthUsernamePassword
      */
     public void onReceivedHttpAuthRequest(WebView view,
             HttpAuthHandler handler, String host, String realm) {
diff --git a/core/java/android/webkit/WebViewClientClassicExt.java b/core/java/android/webkit/WebViewClientClassicExt.java
new file mode 100644
index 0000000..a873585
--- /dev/null
+++ b/core/java/android/webkit/WebViewClientClassicExt.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.net.http.SslError;
+
+/**
+ * Adds WebViewClassic specific extension methods to the WebViewClient callback class.
+ * These are not part of the public WebView API, so the class is hidden.
+ * @hide
+ */
+public class WebViewClientClassicExt extends WebViewClient {
+
+    /**
+     * Notify the host application that an SSL error occurred while loading a
+     * resource, but the WebView chose to proceed anyway based on a
+     * decision retained from a previous response to onReceivedSslError().
+     */
+    public void onProceededAfterSslError(WebView view, SslError error) {
+    }
+
+    /**
+     * Notify the host application to handle a SSL client certificate
+     * request (display the request to the user and ask whether to
+     * proceed with a client certificate or not). The host application
+     * has to call either handler.cancel() or handler.proceed() as the
+     * connection is suspended and waiting for the response. The
+     * default behavior is to cancel, returning no client certificate.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param handler A ClientCertRequestHandler object that will
+     *            handle the user's response.
+     * @param host_and_port The host and port of the requesting server.
+     */
+    public void onReceivedClientCertRequest(WebView view,
+            ClientCertRequestHandler handler, String host_and_port) {
+        handler.cancel();
+    }
+}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 728ddbf..59036e7 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -132,6 +132,8 @@
     private int mRestoredX = 0;
     private int mRestoredY = 0;
 
+    private MockGeolocation mMockGeolocation = new MockGeolocation(this);
+
     private DeviceMotionAndOrientationManager mDeviceMotionAndOrientationManager =
             new DeviceMotionAndOrientationManager(this);
     private DeviceMotionService mDeviceMotionService;
@@ -441,7 +443,7 @@
     }
 
     /**
-     * Notify the browser that the origin has exceeded it's database quota.
+     * Notify the embedding application that the origin has exceeded it's database quota.
      * @param url The URL that caused the overflow.
      * @param databaseIdentifier The identifier of the database.
      * @param quota The current quota for the origin.
@@ -466,12 +468,15 @@
     }
 
     /**
-     * Notify the browser that the appcache has exceeded its max size.
+     * Notify the embedding application that the appcache has reached or exceeded its maximum
+     * allowed storage size.
+     *
      * @param requiredStorage is the amount of storage, in bytes, that would be
      * needed in order for the last appcache operation to succeed.
+     * @param maxSize maximum allowed Application Cache database size, in bytes.
      */
-    protected void reachedMaxAppCacheSize(long requiredStorage) {
-        mCallbackProxy.onReachedMaxAppCacheSize(requiredStorage, getUsedQuota(),
+    protected void reachedMaxAppCacheSize(long requiredStorage, long maxSize) {
+        mCallbackProxy.onReachedMaxAppCacheSize(requiredStorage, maxSize,
                 new WebStorage.QuotaUpdater() {
                     @Override
                     public void updateQuota(long newQuota) {
@@ -560,24 +565,6 @@
     }
 
     /**
-     * Notify the webview that this is an installable web app.
-     */
-    protected void setInstallableWebApp() {
-        mCallbackProxy.setInstallableWebApp();
-    }
-
-    /**
-     * Notify the webview that we want to display the video layer fullscreen.
-     */
-    protected void enterFullscreenForVideoLayer(int layerId, String url) {
-        if (mWebViewClassic == null) return;
-        Message message = Message.obtain(mWebViewClassic.mPrivateHandler,
-                       WebViewClassic.ENTER_FULLSCREEN_VIDEO, layerId, 0);
-        message.obj = url;
-        message.sendToTarget();
-    }
-
-    /**
      * Notify the webview that we want to exit the video fullscreen.
      * This is called through JNI by webcore.
      */
@@ -619,8 +606,6 @@
      */
     private native void nativeNotifyAnimationStarted(int nativeClass);
 
-    private native boolean nativeFocusBoundsChanged(int nativeClass);
-
     private native boolean nativeKey(int nativeClass, int keyCode,
             int unichar, int repeatCount, boolean isShift, boolean isAlt,
             boolean isSym, boolean isDown);
@@ -960,7 +945,7 @@
         public int mMaxLength;
         public Rect mContentBounds;
         public int mNodeLayerId;
-        public Rect mContentRect;
+        public Rect mClientRect;
     }
 
     // mAction of TouchEventData can be MotionEvent.getAction() which uses the
@@ -1199,6 +1184,7 @@
         static final int SET_INITIAL_FOCUS = 224;
 
         static final int SAVE_VIEW_STATE = 225;
+        static final int SET_USE_MOCK_GEOLOCATION = 226;
 
         // Private handler for WebCore messages.
         private Handler mHandler;
@@ -1306,13 +1292,8 @@
                             } else {
                                 xPercent = ((Float) msg.obj).floatValue();
                             }
-                            Rect contentBounds = new Rect();
                             nativeScrollFocusedTextInput(mNativeClass, xPercent,
-                                    msg.arg2, contentBounds);
-                            Message.obtain(
-                                    mWebViewClassic.mPrivateHandler,
-                                    WebViewClassic.UPDATE_CONTENT_BOUNDS,
-                                    contentBounds).sendToTarget();
+                                    msg.arg2);
                             break;
 
                         case LOAD_URL: {
@@ -1660,6 +1641,10 @@
                                     (Set<String>) msg.obj);
                             break;
 
+                        case SET_USE_MOCK_GEOLOCATION:
+                            setUseMockGeolocation();
+                            break;
+
                         case SET_USE_MOCK_DEVICE_ORIENTATION:
                             setUseMockDeviceOrientation();
                             break;
@@ -1708,13 +1693,9 @@
                             nativeInsertText(mNativeClass, (String) msg.obj);
                             break;
                         case SELECT_TEXT: {
-                            int[] args = (int[]) msg.obj;
-                            if (args == null) {
-                                nativeClearTextSelection(mNativeClass);
-                            } else {
-                                nativeSelectText(mNativeClass, args[0],
-                                        args[1], args[2], args[3]);
-                            }
+                            int handleId = (Integer) msg.obj;
+                            nativeSelectText(mNativeClass, handleId,
+                                    msg.arg1, msg.arg2);
                             break;
                         }
                         case SELECT_WORD_AT: {
@@ -2139,8 +2120,8 @@
         return width;
     }
 
-    // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize
-    // callbacks. Computes the sum of database quota for all origins.
+    // Utility method for exceededDatabaseQuota callback. Computes the sum
+    // of WebSQL database quota for all origins.
     private long getUsedQuota() {
         WebStorageClassic webStorage = WebStorageClassic.getInstance();
         Collection<WebStorage.Origin> origins = webStorage.getOriginsSync();
@@ -2192,7 +2173,6 @@
         // only non-null if it is for the first picture set after the first layout
         ViewState mViewState;
         boolean mFirstLayoutForNonStandardLoad;
-        boolean mFocusSizeChanged;
     }
 
     DrawData mLastDrawData = null;
@@ -2217,12 +2197,20 @@
                 mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
             }
             m_skipDrawFlag = false;
+            m_skipDrawFlagLock.notify();
         }
     }
 
     private void webkitDraw() {
         synchronized (m_skipDrawFlagLock) {
             if (m_skipDrawFlag) {
+                try {
+                    // Aggressively throttle webkit to give the UI more CPU
+                    // to catch up with
+                    m_skipDrawFlagLock.wait(50);
+                } catch (InterruptedException e) {}
+            }
+            if (m_skipDrawFlag) {
                 m_drawWasSkipped = true;
                 return;
             }
@@ -2247,7 +2235,6 @@
 
     private void webkitDraw(DrawData draw) {
         if (mWebViewClassic != null) {
-            draw.mFocusSizeChanged = nativeFocusBoundsChanged(mNativeClass);
             draw.mViewSize = new Point(mCurrentViewWidth, mCurrentViewHeight);
             if (mSettings.getUseWideViewPort()) {
                 draw.mMinPrefWidth = Math.max(
@@ -2330,7 +2317,6 @@
                     Log.w(LOGTAG, "Cannot pauseUpdatePicture, core destroyed or not initialized!");
                     return;
                 }
-                core.nativeSetIsPaused(core.mNativeClass, true);
                 core.mDrawIsPaused = true;
             }
         }
@@ -2348,7 +2334,6 @@
                     Log.w(LOGTAG, "Cannot resumeUpdatePicture, core destroyed!");
                     return;
                 }
-                core.nativeSetIsPaused(core.mNativeClass, false);
                 core.mDrawIsPaused = false;
                 // always redraw on resume to reenable gif animations
                 core.mDrawIsScheduled = false;
@@ -2363,13 +2348,13 @@
     //////////////////////////////////////////////////////////////////////////
 
     private void restoreState(int index) {
-        WebBackForwardList list = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic list = mCallbackProxy.getBackForwardList();
         int size = list.getSize();
         for (int i = 0; i < size; i++) {
             list.getItemAtIndex(i).inflate(mBrowserFrame.mNativeFrame);
         }
         mBrowserFrame.mLoadInitFromJava = true;
-        list.restoreIndex(mBrowserFrame.mNativeFrame, index);
+        WebBackForwardListClassic.restoreIndex(mBrowserFrame.mNativeFrame, index);
         mBrowserFrame.mLoadInitFromJava = false;
     }
 
@@ -2787,14 +2772,11 @@
     }
 
     // called by JNI
-    private void updateTextfield(int ptr, boolean changeToPassword,
-            String text, int textGeneration) {
+    private void updateTextfield(int ptr, String text, int textGeneration) {
         if (mWebViewClassic != null) {
-            Message msg = Message.obtain(mWebViewClassic.mPrivateHandler,
+            Message.obtain(mWebViewClassic.mPrivateHandler,
                     WebViewClassic.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
-                    textGeneration, text);
-            msg.getData().putBoolean("password", changeToPassword);
-            msg.sendToTarget();
+                    textGeneration, text).sendToTarget();
         }
     }
 
@@ -2855,7 +2837,7 @@
      * Scroll the focused textfield to (xPercent, y) in document space
      */
     private native void nativeScrollFocusedTextInput(int nativeClass,
-            float xPercent, int y, Rect contentBounds);
+            float xPercent, int y);
 
     // these must be in document space (i.e. not scaled/zoomed).
     private native void nativeSetScrollOffset(int nativeClass,
@@ -3063,6 +3045,22 @@
         mDeviceMotionAndOrientationManager.setUseMock();
     }
 
+    private void setUseMockGeolocation() {
+        mMockGeolocation.setUseMock();
+    }
+
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        mMockGeolocation.setPosition(latitude, longitude, accuracy);
+    }
+
+    public void setMockGeolocationError(int code, String message) {
+        mMockGeolocation.setError(code, message);
+    }
+
+    public void setMockGeolocationPermission(boolean allow) {
+        mMockGeolocation.setPermission(allow);
+    }
+
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
             boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
         mDeviceMotionAndOrientationManager.setMockOrientation(canProvideAlpha, alpha,
@@ -3089,7 +3087,6 @@
         sShouldMonitorWebCoreThread = true;
     }
 
-    private native void nativeSetIsPaused(int nativeClass, boolean isPaused);
     private native void nativePause(int nativeClass);
     private native void nativeResume(int nativeClass);
     private native void nativeFreeMemory(int nativeClass);
@@ -3135,7 +3132,7 @@
     private native String nativeGetText(int nativeClass,
             int startX, int startY, int endX, int endY);
     private native void nativeSelectText(int nativeClass,
-            int startX, int startY, int endX, int endY);
+            int handleId, int x, int y);
     private native void nativeClearTextSelection(int nativeClass);
     private native boolean nativeSelectWordAt(int nativeClass, int x, int y);
     private native void nativeSelectAll(int nativeClass);
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 9d10d67..1987f53 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -23,7 +23,7 @@
  * application has stored any of the following types of browsing data and
  * to clear any such stored data for all WebViews in the application.
  * <ul>
- *  <li>Username/password pairs entered into web forms</li>
+ *  <li>Username/password pairs for web forms</li>
  *  <li>HTTP authentication username/password pairs</li>
  *  <li>Data entered into text fields (e.g. for autocomplete suggestions)</li>
  * </ul>
@@ -43,50 +43,65 @@
     }
 
     /**
-     * Gets whether there are any username/password combinations
-     * from web pages saved.
+     * Gets whether there are any saved username/password pairs for web forms.
+     * Note that these are unrelated to HTTP authentication credentials.
      *
-     * @return true if there are any username/passwords used in web
-     *         forms saved
+     * @return true if there are any saved username/password pairs
+     * @see WebView#savePassword
+     * @see clearUsernamePassword
      */
     public boolean hasUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Clears any username/password combinations saved from web forms.
+     * Clears any saved username/password pairs for web forms.
+     * Note that these are unrelated to HTTP authentication credentials.
+     *
+     * @see WebView#savePassword
+     * @see hasUsernamePassword
      */
     public void clearUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether there are any HTTP authentication username/password combinations saved.
+     * Gets whether there are any saved credentials for HTTP authentication.
      *
-     * @return true if there are any HTTP authentication username/passwords saved
+     * @return whether there are any saved credentials
+     * @see Webview#getHttpAuthUsernamePassword
+     * @see Webview#setHttpAuthUsernamePassword
+     * @see clearHttpAuthUsernamePassword
      */
     public boolean hasHttpAuthUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Clears any HTTP authentication username/passwords that are saved.
+     * Clears any saved credentials for HTTP authentication.
+     *
+     * @see Webview#getHttpAuthUsernamePassword
+     * @see Webview#setHttpAuthUsernamePassword
+     * @see hasHttpAuthUsernamePassword
      */
     public void clearHttpAuthUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether there is any previously-entered form data saved.
+     * Gets whether there is any saved data for web forms.
      *
-     * @return true if there is form data saved
+     * @return whether there is any saved data for web forms
+     * @see clearFormData
      */
     public boolean hasFormData() {
         throw new MustOverrideException();
     }
 
     /**
-     * Clears any stored previously-entered form data.
+     * Clears any saved data for web forms.
+     *
+     * @see hasFormData
      */
     public void clearFormData() {
         throw new MustOverrideException();
diff --git a/core/java/android/webkit/WebViewDatabaseClassic.java b/core/java/android/webkit/WebViewDatabaseClassic.java
index 9b1d4cb..c804b90 100644
--- a/core/java/android/webkit/WebViewDatabaseClassic.java
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -100,6 +100,7 @@
     private boolean mInitialized = false;
 
     WebViewDatabaseClassic(final Context context) {
+        JniUtil.setContext(context);
         new Thread() {
             @Override
             public void run() {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 73ae910..2fc9b39 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -16,14 +16,23 @@
 
 package android.webkit;
 
+import android.os.Build;
+import android.os.StrictMode;
+import android.os.SystemProperties;
 import android.util.Log;
 
+import dalvik.system.PathClassLoader;
+
 /**
  * Top level factory, used creating all the main WebView implementation classes.
  */
 class WebViewFactory {
     // Default Provider factory class name.
-    private static final String DEFAULT_WEB_VIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
+    // 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";
+    private static final String CHROMIUM_WEBVIEW_FACTORY =
+            "com.android.webviewchromium.WebViewChromiumFactoryProvider";
+    private static final String CHROMIUM_WEBVIEW_JAR = "/system/framework/webviewchromium.jar";
 
     private static final String LOGTAG = "WebViewFactory";
 
@@ -38,18 +47,45 @@
         // us honest and minimize usage of WebViewClassic internals when binding the proxy.
         if (sProviderInstance != null) return sProviderInstance;
 
-        sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);
+        // 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)) {
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+            try {
+                sProviderInstance = loadChromiumProvider();
+                if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance);
+            } finally {
+                StrictMode.setThreadPolicy(oldPolicy);
+            }
+        }
+
         if (sProviderInstance == null) {
-            if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
-            sProviderInstance = new WebViewClassic.Factory();
+            if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: "
+                    + DEFAULT_WEBVIEW_FACTORY);
+            sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY,
+                    WebViewFactory.class.getClassLoader());
+            if (sProviderInstance == null) {
+                if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
+                sProviderInstance = new WebViewClassic.Factory();
+            }
         }
         return sProviderInstance;
     }
 
-    private static WebViewFactoryProvider getFactoryByName(String providerName) {
+    // 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() {
+        ClassLoader clazzLoader = new PathClassLoader(CHROMIUM_WEBVIEW_JAR, null,
+                WebViewFactory.class.getClassLoader());
+        return getFactoryByName(CHROMIUM_WEBVIEW_FACTORY, clazzLoader);
+    }
+
+    private static WebViewFactoryProvider getFactoryByName(String providerName,
+            ClassLoader loader) {
         try {
             if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName);
-            Class<?> c = Class.forName(providerName);
+            Class<?> c = Class.forName(providerName, true, loader);
             if (DEBUG) Log.v(LOGTAG, "instantiating factory");
             return (WebViewFactoryProvider) c.newInstance();
         } catch (ClassNotFoundException e) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 867ee54..c9f9fbd 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -37,6 +37,7 @@
 import android.webkit.WebView.HitTestResult;
 import android.webkit.WebView.PictureListener;
 
+import java.io.BufferedWriter;
 import java.io.File;
 import java.util.Map;
 
@@ -220,8 +221,6 @@
 
     public WebSettings getSettings();
 
-    public void emulateShiftHeld();
-
     public void setMapTrackballToArrowKeys(boolean setMap);
 
     public void flingScroll(int vx, int vy);
@@ -236,7 +235,9 @@
 
     public boolean zoomOut();
 
-    public void debugDump();
+    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+    public View findHierarchyView(String className, int hashCode);
 
     //-------------------------------------------------------------------------
     // Provider glue methods
diff --git a/core/java/android/webkit/ZoomControlEmbedded.java b/core/java/android/webkit/ZoomControlEmbedded.java
index d2a0561..ae19832 100644
--- a/core/java/android/webkit/ZoomControlEmbedded.java
+++ b/core/java/android/webkit/ZoomControlEmbedded.java
@@ -90,7 +90,7 @@
             View controls = mZoomButtonsController.getZoomControls();
             ViewGroup.LayoutParams params = controls.getLayoutParams();
             if (params instanceof FrameLayout.LayoutParams) {
-                ((FrameLayout.LayoutParams) params).gravity = Gravity.RIGHT;
+                ((FrameLayout.LayoutParams) params).gravity = Gravity.END;
             }
         }
         return mZoomButtonsController;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 437da59..61c942d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -40,7 +40,6 @@
 import android.util.StateSet;
 import android.view.ActionMode;
 import android.view.ContextMenu.ContextMenuInfo;
-import android.view.FocusFinder;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
@@ -1329,150 +1328,6 @@
     }
 
     @Override
-    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            switch(direction) {
-                case ACCESSIBILITY_FOCUS_BACKWARD: {
-                    View focusable = (getChildCount() > 0) ? getChildAt(getChildCount() - 1) : this;
-                    if (focusable.isAccessibilityFocusable()) {
-                        views.add(focusable);
-                    }
-                } return;
-                case ACCESSIBILITY_FOCUS_FORWARD: {
-                    if (isAccessibilityFocusable()) {
-                        views.add(this);
-                    }
-                } return;
-            }
-        }
-        super.addFocusables(views, direction, focusableMode);
-    }
-
-    @Override
-    public View focusSearch(int direction) {
-        return focusSearch(this, direction);
-    }
-
-    @Override
-    public View focusSearch(View focused, int direction) {
-        switch (direction) {
-            case ACCESSIBILITY_FOCUS_FORWARD: {
-                // If we are the focused view try giving it to the first child.
-                if (focused == this) {
-                    final int childCount = getChildCount();
-                    for (int i = 0; i < childCount; i++) {
-                        View child = getChildAt(i);
-                        if (child.getVisibility() == View.VISIBLE) {
-                            return child;
-                        }
-                    }
-                    return super.focusSearch(this, direction);
-                }
-                // Find the item that has the focused view.
-                final int currentPosition = getPositionForView(focused);
-                if (currentPosition < 0 || currentPosition >= getCount()) {
-                    return super.focusSearch(this, direction);
-                }
-                // Try to advance focus in the current item.
-                View currentItem = getChildAt(currentPosition - getFirstVisiblePosition());
-                if (currentItem.getVisibility() == View.VISIBLE) {
-                    if (currentItem instanceof ViewGroup) {
-                        ViewGroup currentItemGroup = (ViewGroup) currentItem;
-                        View nextFocus = FocusFinder.getInstance().findNextFocus(currentItemGroup,
-                                    focused, direction);
-                        if (nextFocus != null && nextFocus != currentItemGroup
-                                && nextFocus != focused) {
-                            return nextFocus;
-                        }
-                    }
-                }
-                // Try to move focus to the next item.
-                final int nextPosition = currentPosition - getFirstVisiblePosition() + 1;
-                for (int i = nextPosition; i < getChildCount(); i++) {
-                    View child = getChildAt(i);
-                    if (child.getVisibility() == View.VISIBLE) {
-                        return child;
-                    }
-                }
-                // No next item start searching from the list.
-                return super.focusSearch(this, direction);
-            }
-            case ACCESSIBILITY_FOCUS_BACKWARD: {
-                // If we are the focused search from the view that is
-                // as closer to the bottom as possible.
-                if (focused == this) {
-                    final int childCount = getChildCount();
-                    for (int i = childCount - 1; i >= 0; i--) {
-                        View child = getChildAt(i);
-                        if (child.getVisibility() == View.VISIBLE) {
-                            return super.focusSearch(child, direction);
-                        }
-                    }
-                    return super.focusSearch(this, direction);
-                }
-                // Find the item that has the focused view.
-                final int currentPosition = getPositionForView(focused);
-                if (currentPosition < 0 || currentPosition >= getCount()) {
-                    return super.focusSearch(this, direction);
-                }
-
-                View currentItem = getChildAt(currentPosition - getFirstVisiblePosition());
-
-                // If a list item is the focused view we try to find a view
-                // in the previous item since in reverse the item contents
-                // get accessibility focus before the item itself.
-                if (currentItem == focused) {
-                    currentItem = null;
-                    focused = null;
-                    // This list gets accessibility focus after the last item.
-                    final int previousPosition = currentPosition - getFirstVisiblePosition() - 1;
-                    for (int i = previousPosition; i >= 0; i--) {
-                        View child = getChildAt(i);
-                        if (child.getVisibility() == View.VISIBLE) {
-                            currentItem = child;
-                            break;
-                        }
-                    }
-                    if (currentItem == null) {
-                        return this;
-                    }
-                }
-
-                if (currentItem.getVisibility() == View.VISIBLE) {
-                    // Search into the item.
-                    if (currentItem instanceof ViewGroup) {
-                        ViewGroup currentItemGroup = (ViewGroup) currentItem;
-                        View nextFocus = FocusFinder.getInstance().findNextFocus(currentItemGroup,
-                                    focused, direction);
-                        if (nextFocus != null && nextFocus != currentItemGroup
-                                && nextFocus != focused) {
-                            return nextFocus;
-                        }
-                    }
-
-                    // If not item content wants focus we give it to the item.
-                    return currentItem;
-                }
-
-                return super.focusSearch(this, direction);
-            }
-        }
-        return super.focusSearch(focused, direction);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-        final int position = getPositionForView(child);
-        if (position != INVALID_POSITION) {
-            return getChildAt(position - mFirstPosition);
-        }
-        return super.findViewToTakeAccessibilityFocusFromHover(child, descendant);
-    }
-
-    @Override
     public void sendAccessibilityEvent(int eventType) {
         // Since this class calls onScrollChanged even if the mFirstPosition and the
         // child count have not changed we will avoid sending duplicate accessibility
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 4eb169b..2037c3a 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -497,7 +497,7 @@
         // Default activity button.
         final int activityCount = mAdapter.getActivityCount();
         final int historySize = mAdapter.getHistorySize();
-        if (activityCount > 0 && historySize > 0) {
+        if (activityCount==1 || activityCount > 1 && historySize > 0) {
             mDefaultActivityButton.setVisibility(VISIBLE);
             ResolveInfo activity = mAdapter.getDefaultActivity();
             PackageManager packageManager = mContext.getPackageManager();
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index f1804f8..41ab5f2 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -20,6 +20,7 @@
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.util.ValueModel;
 
 
 /**
@@ -55,7 +56,9 @@
  * {@link android.R.styleable#View View Attributes}
  * </p>
  */
-public class CheckBox extends CompoundButton {
+public class CheckBox extends CompoundButton implements ValueEditor<Boolean> {
+    private ValueModel<Boolean> mValueModel = ValueModel.EMPTY;
+
     public CheckBox(Context context) {
         this(context, null);
     }
@@ -79,4 +82,22 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(CheckBox.class.getName());
     }
+
+    @Override
+    public ValueModel<Boolean> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<Boolean> valueModel) {
+        mValueModel = valueModel;
+        setChecked(mValueModel.get());
+    }
+
+    @Override
+    public boolean performClick() {
+        boolean handled = super.performClick();
+        mValueModel.set(isChecked());
+        return handled;
+    }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 0a71c5a..421a324 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -225,26 +225,53 @@
     }
 
     @Override
+    public int getCompoundPaddingLeft() {
+        int padding = super.getCompoundPaddingLeft();
+        if (!isLayoutRtl()) {
+            final Drawable buttonDrawable = mButtonDrawable;
+            if (buttonDrawable != null) {
+                padding += buttonDrawable.getIntrinsicWidth();
+            }
+        }
+        return padding;
+    }
+
+    @Override
+    public int getCompoundPaddingRight() {
+        int padding = super.getCompoundPaddingRight();
+        if (isLayoutRtl()) {
+            final Drawable buttonDrawable = mButtonDrawable;
+            if (buttonDrawable != null) {
+                padding += buttonDrawable.getIntrinsicWidth();
+            }
+        }
+        return padding;
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
         final Drawable buttonDrawable = mButtonDrawable;
         if (buttonDrawable != null) {
             final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
-            final int height = buttonDrawable.getIntrinsicHeight();
+            final int drawableHeight = buttonDrawable.getIntrinsicHeight();
+            final int drawableWidth = buttonDrawable.getIntrinsicWidth();
 
-            int y = 0;
-
+            int top = 0;
             switch (verticalGravity) {
                 case Gravity.BOTTOM:
-                    y = getHeight() - height;
+                    top = getHeight() - drawableHeight;
                     break;
                 case Gravity.CENTER_VERTICAL:
-                    y = (getHeight() - height) / 2;
+                    top = (getHeight() - drawableHeight) / 2;
                     break;
             }
+            int bottom = top + drawableHeight;
+            int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
+            int right = isLayoutRtl() ? getWidth() : drawableWidth;
 
-            buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);
+            buttonDrawable.setBounds(left, top, right, bottom);
             buttonDrawable.draw(canvas);
         }
     }
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index add9d9b..3e9107f 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -34,13 +34,17 @@
  *
  * FIXME: implement separate views for hours/minutes/seconds, so
  * proportional fonts don't shake rendering
+ * 
+ * @deprecated It is recommended you use a {@link TextView} and {@link DateFormat}
+ * to implement the same behavior.
  */
-
+@Deprecated
 public class DigitalClock extends TextView {
 
     Calendar mCalendar;
     private final static String m12 = "h:mm:ss aa";
     private final static String m24 = "k:mm:ss";
+    @SuppressWarnings("FieldCanBeLocal") // We must keep a reference to this observer
     private FormatChangeObserver mFormatChangeObserver;
 
     private Runnable mTicker;
@@ -52,17 +56,15 @@
 
     public DigitalClock(Context context) {
         super(context);
-        initClock(context);
+        initClock();
     }
 
     public DigitalClock(Context context, AttributeSet attrs) {
         super(context, attrs);
-        initClock(context);
+        initClock();
     }
 
-    private void initClock(Context context) {
-        Resources r = mContext.getResources();
-
+    private void initClock() {
         if (mCalendar == null) {
             mCalendar = Calendar.getInstance();
         }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 57e51c2..ec81214 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
@@ -24,6 +25,7 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
+import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -47,7 +49,9 @@
  * {@link android.R.styleable#TextView TextView Attributes},
  * {@link android.R.styleable#View View Attributes}
  */
-public class EditText extends TextView {
+public class EditText extends TextView implements ValueEditor<CharSequence> {
+    private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY;
+
     public EditText(Context context) {
         this(context, null);
     }
@@ -128,4 +132,21 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(EditText.class.getName());
     }
+
+    @Override
+    public ValueModel<CharSequence> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<CharSequence> valueModel) {
+        mValueModel = valueModel;
+        setText(mValueModel.get());
+    }
+
+    @Override
+    void sendAfterTextChanged(Editable text) {
+        super.sendAfterTextChanged(text);
+        mValueModel.set(text);
+    }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c29dd58..7f9dab9 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -978,8 +978,8 @@
                 mSuggestionsPopupWindow.onParentLostFocus();
             }
 
-            // Don't leave us in the middle of a batch edit.
-            mTextView.onEndBatchEdit();
+            // Don't leave us in the middle of a batch edit. Same as in onFocusChanged
+            ensureEndedBatchEdit();
         }
     }
 
@@ -2282,14 +2282,11 @@
                 final SuggestionInfo suggestionInfo = mSuggestionInfos[position];
                 textView.setText(suggestionInfo.text);
 
-                if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
-                    textView.setCompoundDrawablesWithIntrinsicBounds(
-                            com.android.internal.R.drawable.ic_suggestions_add, 0, 0, 0);
-                } else if (suggestionInfo.suggestionIndex == DELETE_TEXT) {
-                    textView.setCompoundDrawablesWithIntrinsicBounds(
-                            com.android.internal.R.drawable.ic_suggestions_delete, 0, 0, 0);
+                if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY ||
+                suggestionInfo.suggestionIndex == DELETE_TEXT) {
+                    textView.setBackgroundColor(Color.TRANSPARENT);
                 } else {
-                    textView.setCompoundDrawables(null, null, null, null);
+                    textView.setBackgroundColor(Color.WHITE);
                 }
 
                 return textView;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 083a952..d2139af 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -181,10 +181,13 @@
     }
 
     public void setScrollbarPosition(int position) {
+        if (position == View.SCROLLBAR_POSITION_DEFAULT) {
+            position = mList.isLayoutRtl() ?
+                    View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
+        }
         mPosition = position;
         switch (position) {
             default:
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 mOverlayDrawable = mOverlayDrawableRight;
                 break;
@@ -229,7 +232,6 @@
         final int viewWidth = mList.getWidth();
         // Bounds are always top right. Y coordinate get's translated during draw
         switch (mPosition) {
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
                 break;
@@ -327,7 +329,6 @@
             }
             int left = 0;
             switch (mPosition) {
-                case View.SCROLLBAR_POSITION_DEFAULT:
                 case View.SCROLLBAR_POSITION_RIGHT:
                     left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
                     break;
@@ -360,7 +361,6 @@
                 int left = 0;
                 switch (mPosition) {
                     default:
-                    case View.SCROLLBAR_POSITION_DEFAULT:
                     case View.SCROLLBAR_POSITION_RIGHT:
                         left = Math.max(0,
                                 mThumbDrawable.getBounds().left - mThumbW - mOverlaySize);
@@ -410,7 +410,6 @@
         if (mThumbDrawable != null) {
             switch (mPosition) {
                 default:
-                case View.SCROLLBAR_POSITION_DEFAULT:
                 case View.SCROLLBAR_POSITION_RIGHT:
                     mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH);
                     break;
@@ -820,7 +819,6 @@
         boolean inTrack = false;
         switch (mPosition) {
             default:
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 inTrack = x > mList.getWidth() - mThumbW;
                 break;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index d019d8c..a025610 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -55,7 +55,7 @@
  */
 @RemoteView
 public class FrameLayout extends ViewGroup {
-    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;
+    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
 
     @ViewDebug.ExportedProperty(category = "measurement")
     boolean mMeasureAllChildren = false;
@@ -603,6 +603,12 @@
          */
         public int gravity = -1;
 
+        @Override
+        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
+            width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
+            height = a.getLayoutDimension(heightAttr, MATCH_PARENT);
+        }
+
         /**
          * {@inheritDoc}
          */
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 37e0b90..b6fcb03 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -94,7 +94,7 @@
     private View mReferenceView = null;
     private View mReferenceViewInSelectedRow = null;
 
-    private int mGravity = Gravity.LEFT;
+    private int mGravity = Gravity.START;
 
     private final Rect mTempRect = new Rect();
 
@@ -300,9 +300,18 @@
         final int columnWidth = mColumnWidth;
         final int horizontalSpacing = mHorizontalSpacing;
 
+        final boolean isLayoutRtl = isLayoutRtl();
+
         int last;
-        int nextLeft = mListPadding.left +
-                ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+        int nextLeft;
+
+        if (isLayoutRtl) {
+            nextLeft = getWidth() - mListPadding.right - columnWidth -
+                    ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+        } else {
+            nextLeft = mListPadding.left +
+                    ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+        }
 
         if (!mStackFromBottom) {
             last = Math.min(startPos + mNumColumns, mItemCount);
@@ -311,7 +320,8 @@
             startPos = Math.max(0, startPos - mNumColumns + 1);
 
             if (last - startPos < mNumColumns) {
-                nextLeft += (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
+                final int deltaLeft = (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
+                nextLeft += (isLayoutRtl ? -1 : +1) * deltaLeft;
             }
         }
 
@@ -330,7 +340,7 @@
             final int where = flow ? -1 : pos - startPos;
             child = makeAndAddView(pos, y, flow, nextLeft, selected, where);
 
-            nextLeft += columnWidth;
+            nextLeft += (isLayoutRtl ? -1 : +1) * columnWidth;
             if (pos < last - 1) {
                 nextLeft += horizontalSpacing;
             }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index cf28da4..f259597 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -193,15 +193,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public int getResolvedLayoutDirection(Drawable dr) {
-        return (dr == mDrawable) ?
-                getResolvedLayoutDirection() : super.getResolvedLayoutDirection(dr);
-    }
-
     @Override
     public boolean hasOverlappingRendering() {
         return (getBackground() != null);
@@ -675,6 +666,7 @@
                 d.setState(getDrawableState());
             }
             d.setLevel(mLevel);
+            d.setLayoutDirection(getLayoutDirection());
             mDrawableWidth = d.getIntrinsicWidth();
             mDrawableHeight = d.getIntrinsicHeight();
             applyColorMod();
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 09c0129..ea85325 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -345,28 +345,42 @@
 
     void drawDividersHorizontal(Canvas canvas) {
         final int count = getVirtualChildCount();
+        final boolean isLayoutRtl = isLayoutRtl();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
 
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                    final int left = child.getLeft() - lp.leftMargin - mDividerWidth;
-                    drawVerticalDivider(canvas, left);
+                    final int position;
+                    if (isLayoutRtl) {
+                        position = child.getRight() + lp.rightMargin;
+                    } else {
+                        position = child.getLeft() - lp.leftMargin - mDividerWidth;
+                    }
+                    drawVerticalDivider(canvas, position);
                 }
             }
         }
 
         if (hasDividerBeforeChildAt(count)) {
             final View child = getVirtualChildAt(count - 1);
-            int right = 0;
+            int position;
             if (child == null) {
-                right = getWidth() - getPaddingRight() - mDividerWidth;
+                if (isLayoutRtl) {
+                    position = getPaddingLeft();
+                } else {
+                    position = getWidth() - getPaddingRight() - mDividerWidth;
+                }
             } else {
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                right = child.getRight() + lp.rightMargin;
+                if (isLayoutRtl) {
+                    position = child.getLeft() - lp.leftMargin - mDividerWidth;
+                } else {
+                    position = child.getRight() + lp.rightMargin;
+                }
             }
-            drawVerticalDivider(canvas, right);
+            drawVerticalDivider(canvas, position);
         }
     }
 
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index a458f57..eabcb80 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1417,19 +1417,6 @@
     }
 
     @Override
-    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        // We do not want the real descendant to be considered focus search
-        // since it is managed by the accessibility node provider.
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (isAccessibilityFocusable()) {
-                views.add(this);
-                return;
-            }
-        }
-        super.addFocusables(views, direction, focusableMode);
-    }
-
-    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         event.setClassName(NumberPicker.class.getName());
@@ -2297,78 +2284,6 @@
             return super.performAction(virtualViewId, action, arguments);
         }
 
-        @Override
-        public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
-            return createAccessibilityNodeInfo(mAccessibilityFocusedView);
-        }
-
-        @Override
-        public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
-            switch (direction) {
-                case View.ACCESSIBILITY_FOCUS_DOWN:
-                case View.ACCESSIBILITY_FOCUS_FORWARD: {
-                    switch (mAccessibilityFocusedView) {
-                        case UNDEFINED: {
-                            return createAccessibilityNodeInfo(View.NO_ID);
-                        }
-                        case View.NO_ID: {
-                            if (hasVirtualDecrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_DECREMENT: {
-                            return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
-                        }
-                        case VIRTUAL_VIEW_ID_INPUT: {
-                            if (hasVirtualIncrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_INCREMENT: {
-                            View nextFocus = NumberPicker.this.focusSearch(direction);
-                            if (nextFocus != null) {
-                                return nextFocus.createAccessibilityNodeInfo();
-                            }
-                            return null;
-                        }
-                    }
-                } break;
-                case View.ACCESSIBILITY_FOCUS_UP:
-                case View.ACCESSIBILITY_FOCUS_BACKWARD: {
-                    switch (mAccessibilityFocusedView) {
-                        case UNDEFINED: {
-                            return createAccessibilityNodeInfo(View.NO_ID);
-                        }
-                        case View.NO_ID: {
-                            if (hasVirtualIncrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_INCREMENT: {
-                            return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
-                        }
-                        case VIRTUAL_VIEW_ID_INPUT: {
-                            if (hasVirtualDecrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_DECREMENT: {
-                            View nextFocus = NumberPicker.this.focusSearch(direction);
-                            if (nextFocus != null) {
-                                return nextFocus.createAccessibilityNodeInfo();
-                            }
-                            return null;
-                        }
-                    }
-                } break;
-            }
-            return null;
-        }
-
         public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) {
             switch (virtualViewId) {
                 case VIRTUAL_VIEW_ID_DECREMENT: {
@@ -2506,14 +2421,22 @@
             info.setParent((View) getParentForAccessibility());
             info.setEnabled(NumberPicker.this.isEnabled());
             info.setScrollable(true);
+
+            final float applicationScale =
+                getContext().getResources().getCompatibilityInfo().applicationScale;
+
             Rect boundsInParent = mTempRect;
             boundsInParent.set(left, top, right, bottom);
+            boundsInParent.scale(applicationScale);
             info.setBoundsInParent(boundsInParent);
+
             info.setVisibleToUser(isVisibleToUser());
+
             Rect boundsInScreen = boundsInParent;
             int[] locationOnScreen = mTempArray;
             getLocationOnScreen(locationOnScreen);
             boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
+            boundsInScreen.scale(applicationScale);
             info.setBoundsInScreen(boundsInScreen);
 
             if (mAccessibilityFocusedView != View.NO_ID) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index f442912..af3365e 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -835,7 +835,7 @@
        
         preparePopup(p);
         if (gravity == Gravity.NO_GRAVITY) {
-            gravity = Gravity.TOP | Gravity.LEFT;
+            gravity = Gravity.TOP | Gravity.START;
         }
         p.gravity = gravity;
         p.x = x;
@@ -1003,7 +1003,7 @@
         // screen. The view is then positioned to the appropriate location
         // by setting the x and y offsets to match the anchor's bottom
         // left corner
-        p.gravity = Gravity.LEFT | Gravity.TOP;
+        p.gravity = Gravity.START | Gravity.TOP;
         p.width = mLastWidth = mWidth;
         p.height = mLastHeight = mHeight;
         if (mBackground != null) {
@@ -1100,7 +1100,7 @@
         
         boolean onTop = false;
 
-        p.gravity = Gravity.LEFT | Gravity.TOP;
+        p.gravity = Gravity.START | Gravity.TOP;
         
         anchor.getLocationOnScreen(mScreenLocation);
         final Rect displayFrame = new Rect();
@@ -1134,7 +1134,7 @@
             onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) <
                     (mScreenLocation[1] - yoff - displayFrame.top);
             if (onTop) {
-                p.gravity = Gravity.LEFT | Gravity.BOTTOM;
+                p.gravity = Gravity.START | Gravity.BOTTOM;
                 p.y = root.getHeight() - mDrawingLocation[1] + yoff;
             } else {
                 p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index f3f18d5..a28e9ff 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -354,7 +354,7 @@
                     Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
             shapeDrawable.getPaint().setShader(bitmapShader);
 
-            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
+            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.START,
                     ClipDrawable.HORIZONTAL) : shapeDrawable;
         }
         
@@ -478,6 +478,9 @@
             d.setCallback(this);
         }
         mIndeterminateDrawable = d;
+        if (mIndeterminateDrawable != null) {
+            mIndeterminateDrawable.setLayoutDirection(getLayoutDirection());
+        }
         if (mIndeterminate) {
             mCurrentDrawable = d;
             postInvalidate();
@@ -517,6 +520,7 @@
 
         if (d != null) {
             d.setCallback(this);
+            d.setLayoutDirection(getLayoutDirection());
 
             // Make sure the ProgressBar is always tall enough
             int drawableHeight = d.getMinimumHeight();
@@ -975,15 +979,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public int getResolvedLayoutDirection(Drawable who) {
-        return (who == mProgressDrawable || who == mIndeterminateDrawable) ?
-            getResolvedLayoutDirection() : super.getResolvedLayoutDirection(who);
-    }
-
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         updateDrawableBounds(w, h);
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index f217c9c..42d63b2 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -297,33 +297,6 @@
         public LayoutParams(MarginLayoutParams source) {
             super(source);
         }
-
-        /**
-         * <p>Fixes the child's width to
-         * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the child's
-         * height to  {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
-         * when not specified in the XML file.</p>
-         *
-         * @param a the styled attributes set
-         * @param widthAttr the width attribute to fetch
-         * @param heightAttr the height attribute to fetch
-         */
-        @Override
-        protected void setBaseAttributes(TypedArray a,
-                int widthAttr, int heightAttr) {
-
-            if (a.hasValue(widthAttr)) {
-                width = a.getLayoutDimension(widthAttr, "layout_width");
-            } else {
-                width = WRAP_CONTENT;
-            }
-            
-            if (a.hasValue(heightAttr)) {
-                height = a.getLayoutDimension(heightAttr, "layout_height");
-            } else {
-                height = WRAP_CONTENT;
-            }
-        }
     }
 
     /**
@@ -376,7 +349,7 @@
                 int id = child.getId();
                 // generates an id if it's missing
                 if (id == View.NO_ID) {
-                    id = child.hashCode();
+                    id = View.generateViewId();
                     child.setId(id);
                 }
                 ((RadioButton) child).setOnCheckedChangeWidgetListener(
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 569cf99..a811cc2 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -149,8 +149,34 @@
      * bounds of its RelativeLayout parent.
      */
     public static final int CENTER_VERTICAL          = 15;
+    /**
+     * Rule that aligns a child's end edge with another child's start edge.
+     */
+    public static final int START_OF                 = 16;
+    /**
+     * Rule that aligns a child's start edge with another child's end edge.
+     */
+    public static final int END_OF                   = 17;
+    /**
+     * Rule that aligns a child's start edge with another child's start edge.
+     */
+    public static final int ALIGN_START              = 18;
+    /**
+     * Rule that aligns a child's end edge with another child's end edge.
+     */
+    public static final int ALIGN_END                = 19;
+    /**
+     * Rule that aligns the child's start edge with its RelativeLayout
+     * parent's start edge.
+     */
+    public static final int ALIGN_PARENT_START       = 20;
+    /**
+     * Rule that aligns the child's end edge with its RelativeLayout
+     * parent's end edge.
+     */
+    public static final int ALIGN_PARENT_END         = 21;
 
-    private static final int VERB_COUNT              = 16;
+    private static final int VERB_COUNT              = 22;
 
 
     private static final int[] RULES_VERTICAL = {
@@ -158,13 +184,13 @@
     };
 
     private static final int[] RULES_HORIZONTAL = {
-            LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT
+            LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT, START_OF, END_OF, ALIGN_START, ALIGN_END
     };
 
     private View mBaselineView = null;
     private boolean mHasBaselineAlignedChild;
 
-    private int mGravity = Gravity.LEFT | Gravity.TOP;
+    private int mGravity = Gravity.START | Gravity.TOP;
     private final Rect mContentBounds = new Rect();
     private final Rect mSelfBounds = new Rect();
     private int mIgnoreGravity;
@@ -204,7 +230,7 @@
 
     /**
      * Defines which View is ignored when the gravity is applied. This setting has no
-     * effect if the gravity is <code>Gravity.LEFT | Gravity.TOP</code>.
+     * effect if the gravity is <code>Gravity.START | Gravity.TOP</code>.
      *
      * @param viewId The id of the View to be ignored by gravity, or 0 if no View
      *        should be ignored.
@@ -234,7 +260,7 @@
 
     /**
      * Describes how the child views are positioned. Defaults to
-     * <code>Gravity.LEFT | Gravity.TOP</code>.
+     * <code>Gravity.START | Gravity.TOP</code>.
      *
      * <p>Note that since RelativeLayout considers the positioning of each child
      * relative to one another to be significant, setting gravity will affect
@@ -369,7 +395,7 @@
 
         View ignore = null;
         int gravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
-        final boolean horizontalGravity = gravity != Gravity.LEFT && gravity != 0;
+        final boolean horizontalGravity = gravity != Gravity.START && gravity != 0;
         gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
         final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;
 
@@ -457,6 +483,8 @@
             }
         }
 
+        final int layoutDirection = getResolvedLayoutDirection();
+
         if (isWrapContentWidth) {
             // Width already has left padding in it since it was calculated by looking at
             // the right of each child view
@@ -474,7 +502,7 @@
                     View child = getChildAt(i);
                     if (child.getVisibility() != GONE) {
                         LayoutParams params = (LayoutParams) child.getLayoutParams();
-                        final int[] rules = params.getRules();
+                        final int[] rules = params.getRules(layoutDirection);
                         if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
                             centerHorizontal(child, params, width);
                         } else if (rules[ALIGN_PARENT_RIGHT] != 0) {
@@ -504,7 +532,7 @@
                     View child = getChildAt(i);
                     if (child.getVisibility() != GONE) {
                         LayoutParams params = (LayoutParams) child.getLayoutParams();
-                        final int[] rules = params.getRules();
+                        final int[] rules = params.getRules(layoutDirection);
                         if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
                             centerVertical(child, params, height);
                         } else if (rules[ALIGN_PARENT_BOTTOM] != 0) {
@@ -523,7 +551,6 @@
                     height - mPaddingBottom);
 
             final Rect contentBounds = mContentBounds;
-            final int layoutDirection = getResolvedLayoutDirection();
             Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,
                     layoutDirection);
 
@@ -551,7 +578,8 @@
     }
 
     private void alignBaseline(View child, LayoutParams params) {
-        int[] rules = params.getRules();
+        final int layoutDirection = getResolvedLayoutDirection();
+        int[] rules = params.getRules(layoutDirection);
         int anchorBaseline = getRelatedViewBaseline(rules, ALIGN_BASELINE);
 
         if (anchorBaseline != -1) {
@@ -619,7 +647,7 @@
 
     /**
      * Get a measure spec that accounts for all of the constraints on this view.
-     * This includes size contstraints imposed by the RelativeLayout as well as
+     * This includes size constraints imposed by the RelativeLayout as well as
      * the View's desired dimension.
      *
      * @param childStart The left or top field of the child's layout params
@@ -672,7 +700,7 @@
                     childSpecSize = childSize;
                 }
             } else if (childSize == LayoutParams.MATCH_PARENT) {
-                // Child wanted to be as big as possible. Give all availble
+                // Child wanted to be as big as possible. Give all available
                 // space
                 childSpecMode = MeasureSpec.EXACTLY;
                 childSpecSize = maxAvailable;
@@ -681,7 +709,7 @@
                 // to communicate available space if we know
                 // our max size
                 if (maxAvailable >= 0) {
-                    // We have a maxmum size in this dimension.
+                    // We have a maximum size in this dimension.
                     childSpecMode = MeasureSpec.AT_MOST;
                     childSpecSize = maxAvailable;
                 } else {
@@ -699,7 +727,9 @@
     private boolean positionChildHorizontal(View child, LayoutParams params, int myWidth,
             boolean wrapContent) {
 
-        int[] rules = params.getRules();
+        final int layoutDirection = getResolvedLayoutDirection();
+        int[] rules = params.getRules(layoutDirection);
+        params.onResolveLayoutDirection(layoutDirection);
 
         if (params.mLeft < 0 && params.mRight >= 0) {
             // Right is fixed, but left varies
@@ -718,11 +748,18 @@
                 }
                 return true;
             } else {
-                params.mLeft = mPaddingLeft + params.leftMargin;
-                params.mRight = params.mLeft + child.getMeasuredWidth();
+                // This is the default case. For RTL we start from the right and for LTR we start
+                // from the left. This will give LEFT/TOP for LTR and RIGHT/TOP for RTL.
+                if (isLayoutRtl()) {
+                    params.mRight = myWidth - mPaddingRight- params.rightMargin;
+                    params.mLeft = params.mRight - child.getMeasuredWidth();
+                } else {
+                    params.mLeft = mPaddingLeft + params.leftMargin;
+                    params.mRight = params.mLeft + child.getMeasuredWidth();
+                }
             }
         }
-        return rules[ALIGN_PARENT_RIGHT] != 0;
+        return rules[ALIGN_PARENT_END] != 0;
     }
 
     private boolean positionChildVertical(View child, LayoutParams params, int myHeight,
@@ -755,7 +792,8 @@
     }
 
     private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
-        int[] rules = childParams.getRules();
+        final int layoutDirection = getResolvedLayoutDirection();
+        int[] rules = childParams.getRules(layoutDirection);
         RelativeLayout.LayoutParams anchorParams;
 
         // -1 indicated a "soft requirement" in that direction. For example:
@@ -945,8 +983,8 @@
             if (child.getVisibility() != GONE) {
                 RelativeLayout.LayoutParams st =
                         (RelativeLayout.LayoutParams) child.getLayoutParams();
+                st.onResolveLayoutDirection(getResolvedLayoutDirection());
                 child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom);
-
             }
         }
     }
@@ -1061,6 +1099,12 @@
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerInParent
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerHorizontal
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerVertical
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toStartOf
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toEndOf
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignStart
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignEnd
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentStart
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentEnd
      */
     public static class LayoutParams extends ViewGroup.MarginLayoutParams {
         @ViewDebug.ExportedProperty(category = "layout", resolveId = true, indexMapping = {
@@ -1079,15 +1123,28 @@
             @ViewDebug.IntToString(from = CENTER_IN_PARENT,    to = "center"),
             @ViewDebug.IntToString(from = CENTER_VERTICAL,     to = "centerVertical"),
             @ViewDebug.IntToString(from = LEFT_OF,             to = "leftOf"),
-            @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf")
+            @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf"),
+            @ViewDebug.IntToString(from = ALIGN_START,         to = "alignStart"),
+            @ViewDebug.IntToString(from = ALIGN_END,           to = "alignEnd"),
+            @ViewDebug.IntToString(from = ALIGN_PARENT_START,  to = "alignParentStart"),
+            @ViewDebug.IntToString(from = ALIGN_PARENT_END,    to = "alignParentEnd"),
+            @ViewDebug.IntToString(from = START_OF,            to = "startOf"),
+            @ViewDebug.IntToString(from = END_OF,              to = "endOf")
         }, mapping = {
             @ViewDebug.IntToString(from = TRUE, to = "true"),
             @ViewDebug.IntToString(from = 0,    to = "false/NO_ID")
         })
+
         private int[] mRules = new int[VERB_COUNT];
+        private int[] mInitialRules = new int[VERB_COUNT];
 
         private int mLeft, mTop, mRight, mBottom;
 
+        private int mStart = DEFAULT_RELATIVE;
+        private int mEnd = DEFAULT_RELATIVE;
+
+        private boolean mRulesChanged = false;
+
         /**
          * When true, uses the parent as the anchor if the anchor doesn't exist or if
          * the anchor's visibility is GONE.
@@ -1102,6 +1159,7 @@
                     com.android.internal.R.styleable.RelativeLayout_Layout);
 
             final int[] rules = mRules;
+            final int[] initialRules = mInitialRules;
 
             final int N = a.getIndexCount();
             for (int i = 0; i < N; i++) {
@@ -1158,9 +1216,31 @@
                     case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical:
                         rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0;
                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toStartOf:
+                        rules[START_OF] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toEndOf:
+                        rules[END_OF] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignStart:
+                        rules[ALIGN_START] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignEnd:
+                        rules[ALIGN_END] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentStart:
+                        rules[ALIGN_PARENT_START] = a.getBoolean(attr, false) ? TRUE : 0;
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentEnd:
+                        rules[ALIGN_PARENT_END] = a.getBoolean(attr, false) ? TRUE : 0;
+                        break;
                 }
             }
 
+            for (int n = LEFT_OF; n < VERB_COUNT; n++) {
+                initialRules[n] = rules[n];
+            }
+
             a.recycle();
         }
 
@@ -1192,7 +1272,7 @@
          * Adds a layout rule to be interpreted by the RelativeLayout. This
          * method should only be used for constraints that don't refer to another sibling
          * (e.g., CENTER_IN_PARENT) or take a boolean value ({@link RelativeLayout#TRUE}
-         * for true or - for false). To specify a verb that takes a subject, use
+         * for true or 0 for false). To specify a verb that takes a subject, use
          * {@link #addRule(int, int)} instead.
          *
          * @param verb One of the verbs defined by
@@ -1202,6 +1282,8 @@
          */
         public void addRule(int verb) {
             mRules[verb] = TRUE;
+            mInitialRules[verb] = TRUE;
+            mRulesChanged = true;
         }
 
         /**
@@ -1220,12 +1302,73 @@
          */
         public void addRule(int verb, int anchor) {
             mRules[verb] = anchor;
+            mInitialRules[verb] = anchor;
+            mRulesChanged = true;
+        }
+
+        private boolean hasRelativeRules() {
+            return (mInitialRules[START_OF] != 0 || mInitialRules[END_OF] != 0 ||
+                    mInitialRules[ALIGN_START] != 0 || mInitialRules[ALIGN_END] != 0 ||
+                    mInitialRules[ALIGN_PARENT_START] != 0 || mInitialRules[ALIGN_PARENT_END] != 0);
+        }
+
+        private void resolveRules(int layoutDirection) {
+            final boolean isLayoutRtl = (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+            // Reset to initial state
+            for (int n = LEFT_OF; n < VERB_COUNT; n++) {
+                mRules[n] = mInitialRules[n];
+            }
+            // Apply rules depending on direction
+            if (mRules[ALIGN_START] != 0) {
+                mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START];
+            }
+            if (mRules[ALIGN_END] != 0) {
+                mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END];
+            }
+            if (mRules[START_OF] != 0) {
+                mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF];
+            }
+            if (mRules[END_OF] != 0) {
+                mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF];
+            }
+            if (mRules[ALIGN_PARENT_START] != 0) {
+                mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
+            }
+            if (mRules[ALIGN_PARENT_END] != 0) {
+                mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
+            }
+            mRulesChanged = false;
         }
 
         /**
          * Retrieves a complete list of all supported rules, where the index is the rule
          * verb, and the element value is the value specified, or "false" if it was never
-         * set.
+         * set. If there are relative rules defined (*_START / *_END), they will be resolved
+         * depending on the layout direction.
+         *
+         * @param layoutDirection the direction of the layout.
+         *                        Should be either {@link View#LAYOUT_DIRECTION_LTR}
+         *                        or {@link View#LAYOUT_DIRECTION_RTL}
+         * @return the supported rules
+         * @see #addRule(int, int)
+         *
+         * @hide
+         */
+        public int[] getRules(int layoutDirection) {
+            if (hasRelativeRules() &&
+                    (mRulesChanged || layoutDirection != getLayoutDirection())) {
+                resolveRules(layoutDirection);
+                if (layoutDirection != getLayoutDirection()) {
+                    setLayoutDirection(layoutDirection);
+                }
+            }
+            return mRules;
+        }
+
+        /**
+         * Retrieves a complete list of all supported rules, where the index is the rule
+         * verb, and the element value is the value specified, or "false" if it was never
+         * set. There will be no resolution of relative rules done.
          *
          * @return the supported rules
          * @see #addRule(int, int)
@@ -1233,6 +1376,24 @@
         public int[] getRules() {
             return mRules;
         }
+
+        @Override
+        public void onResolveLayoutDirection(int layoutDirection) {
+            final boolean isLayoutRtl = isLayoutRtl();
+            if (isLayoutRtl) {
+                if (mStart != DEFAULT_RELATIVE) mRight = mStart;
+                if (mEnd != DEFAULT_RELATIVE) mLeft = mEnd;
+            } else {
+                if (mStart != DEFAULT_RELATIVE) mLeft = mStart;
+                if (mEnd != DEFAULT_RELATIVE) mRight = mEnd;
+            }
+
+            if (hasRelativeRules() && layoutDirection != getLayoutDirection()) {
+                resolveRules(layoutDirection);
+            }
+            // This will set the layout direction
+            super.onResolveLayoutDirection(layoutDirection);
+        }
     }
 
     private static class DependencyGraph {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 4710798f..dd05a03 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1663,12 +1663,19 @@
     }
 
     /**
+     * Equivalent to calling {@link 
+     * TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
+     *
      * @param viewId The id of the view whose text should change
-     * @param start The id of a drawable to place before the text (relative to the
+     * @param start The id of a drawable to place before the text (relative to the 
      * layout direction), or 0
      * @param top The id of a drawable to place above the text, or 0
      * @param end The id of a drawable to place after the text, or 0
+<<<<<<< HEAD
+     * @param bottom The id of a drawable to place below the text, or 0 
+=======
      * @param bottom The id of a drawable to place below the text, or 0
+>>>>>>> 0a43f67e
      */
     public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) {
         addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom));
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index 2737f94..a6486a8 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -33,7 +34,7 @@
  *
  * @attr ref android.R.styleable#SeekBar_thumb
  */
-public class SeekBar extends AbsSeekBar {
+public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> {
 
     /**
      * A callback that notifies clients when the progress level has been
@@ -69,8 +70,9 @@
         void onStopTrackingTouch(SeekBar seekBar);
     }
 
+    private ValueModel<Integer> mValueModel = ValueModel.EMPTY;
     private OnSeekBarChangeListener mOnSeekBarChangeListener;
-    
+
     public SeekBar(Context context) {
         this(context, null);
     }
@@ -89,9 +91,23 @@
 
         if (mOnSeekBarChangeListener != null) {
             mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
+            if (fromUser) {
+                mValueModel.set(getProgress());
+            }
         }
     }
 
+    @Override
+    public ValueModel<Integer> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<Integer> valueModel) {
+        mValueModel = valueModel;
+        setProgress(mValueModel.get());
+    }
+
     /**
      * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
      * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index 14edd10..517246b 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -78,7 +78,12 @@
  * @attr ref android.R.styleable#SlidingDrawer_orientation
  * @attr ref android.R.styleable#SlidingDrawer_allowSingleTap
  * @attr ref android.R.styleable#SlidingDrawer_animateOnClick
+ * 
+ * @deprecated This class is not supported anymore. It is recommended you
+ * base your own implementation on the source code for the Android Open
+ * Source Project if you must use it in your application.
  */
+@Deprecated
 public class SlidingDrawer extends ViewGroup {
     public static final int ORIENTATION_HORIZONTAL = 0;
     public static final int ORIENTATION_VERTICAL = 1;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 64834b2..ecd7277 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -355,7 +355,7 @@
     public void setGravity(int gravity) {
         if (mGravity != gravity) {
             if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
-                gravity |= Gravity.LEFT;
+                gravity |= Gravity.START;
             }
             mGravity = gravity;
             requestLayout();
@@ -460,7 +460,7 @@
     /**
      * Creates and positions all views for this Spinner.
      *
-     * @param delta Change in the selected position. +1 moves selection is moving to the right,
+     * @param delta Change in the selected position. +1 means selection is moving to the right,
      * so views are scrolling to the left. -1 means selection is moving to the left.
      */
     @Override
@@ -492,7 +492,9 @@
         View sel = makeAndAddView(mSelectedPosition);
         int width = sel.getMeasuredWidth();
         int selectedOffset = childrenLeft;
-        switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+        final int layoutDirection = getResolvedLayoutDirection();
+        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
             case Gravity.CENTER_HORIZONTAL:
                 selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
                 break;
@@ -939,19 +941,18 @@
         @Override
         public void show() {
             final Drawable background = getBackground();
-            int bgOffset = 0;
+            int hOffset = 0;
             if (background != null) {
                 background.getPadding(mTempRect);
-                bgOffset = -mTempRect.left;
+                hOffset = isLayoutRtl() ? mTempRect.right : -mTempRect.left;
             } else {
                 mTempRect.left = mTempRect.right = 0;
             }
 
             final int spinnerPaddingLeft = Spinner.this.getPaddingLeft();
+            final int spinnerPaddingRight = Spinner.this.getPaddingRight();
+            final int spinnerWidth = Spinner.this.getWidth();
             if (mDropDownWidth == WRAP_CONTENT) {
-                final int spinnerWidth = Spinner.this.getWidth();
-                final int spinnerPaddingRight = Spinner.this.getPaddingRight();
-
                 int contentWidth =  measureContentWidth(
                         (SpinnerAdapter) mAdapter, getBackground());
                 final int contentWidthLimit = mContext.getResources()
@@ -959,17 +960,20 @@
                 if (contentWidth > contentWidthLimit) {
                     contentWidth = contentWidthLimit;
                 }
-
                 setContentWidth(Math.max(
                        contentWidth, spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight));
             } else if (mDropDownWidth == MATCH_PARENT) {
-                final int spinnerWidth = Spinner.this.getWidth();
-                final int spinnerPaddingRight = Spinner.this.getPaddingRight();
                 setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight);
             } else {
                 setContentWidth(mDropDownWidth);
             }
-            setHorizontalOffset(bgOffset + spinnerPaddingLeft);
+
+            if (isLayoutRtl()) {
+                hOffset += spinnerWidth - spinnerPaddingRight - getWidth();
+            } else {
+                hOffset += spinnerPaddingLeft;
+            }
+            setHorizontalOffset(hOffset);
             setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
             super.show();
             getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 56f6651..5d6491d 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -480,12 +480,6 @@
 
     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-
         if (mOnLayout == null) {
             mOnLayout = makeLayout(mTextOn);
         }
@@ -501,34 +495,6 @@
 
         mThumbWidth = maxTextWidth + mThumbTextPadding * 2;
 
-        switch (widthMode) {
-            case MeasureSpec.AT_MOST:
-                widthSize = Math.min(widthSize, switchWidth);
-                break;
-
-            case MeasureSpec.UNSPECIFIED:
-                widthSize = switchWidth;
-                break;
-
-            case MeasureSpec.EXACTLY:
-                // Just use what we were given
-                break;
-        }
-
-        switch (heightMode) {
-            case MeasureSpec.AT_MOST:
-                heightSize = Math.min(heightSize, switchHeight);
-                break;
-
-            case MeasureSpec.UNSPECIFIED:
-                heightSize = switchHeight;
-                break;
-
-            case MeasureSpec.EXACTLY:
-                // Just use what we were given
-                break;
-        }
-
         mSwitchWidth = switchWidth;
         mSwitchHeight = switchHeight;
 
@@ -662,7 +628,7 @@
             mVelocityTracker.computeCurrentVelocity(1000);
             float xvel = mVelocityTracker.getXVelocity();
             if (Math.abs(xvel) > mMinFlingVelocity) {
-                newState = xvel > 0;
+                newState = isLayoutRtl() ? (xvel < 0) : (xvel > 0);
             } else {
                 newState = getTargetCheckedState();
             }
@@ -680,13 +646,25 @@
     }
 
     private boolean getTargetCheckedState() {
-        return mThumbPosition >= getThumbScrollRange() / 2;
+        if (isLayoutRtl()) {
+            return mThumbPosition <= getThumbScrollRange() / 2;
+        } else {
+            return mThumbPosition >= getThumbScrollRange() / 2;
+        }
+    }
+
+    private void setThumbPosition(boolean checked) {
+        if (isLayoutRtl()) {
+            mThumbPosition = checked ? 0 : getThumbScrollRange();
+        } else {
+            mThumbPosition = checked ? getThumbScrollRange() : 0;
+        }
     }
 
     @Override
     public void setChecked(boolean checked) {
         super.setChecked(checked);
-        mThumbPosition = checked ? getThumbScrollRange() : 0;
+        setThumbPosition(checked);
         invalidate();
     }
 
@@ -694,10 +672,19 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
 
-        mThumbPosition = isChecked() ? getThumbScrollRange() : 0;
+        setThumbPosition(isChecked());
 
-        int switchRight = getWidth() - getPaddingRight();
-        int switchLeft = switchRight - mSwitchWidth;
+        int switchRight;
+        int switchLeft;
+
+        if (isLayoutRtl()) {
+            switchLeft = getPaddingLeft();
+            switchRight = switchLeft + mSwitchWidth;
+        } else {
+            switchRight = getWidth() - getPaddingRight();
+            switchLeft = switchRight - mSwitchWidth;
+        }
+
         int switchTop = 0;
         int switchBottom = 0;
         switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) {
@@ -772,7 +759,22 @@
     }
 
     @Override
+    public int getCompoundPaddingLeft() {
+        if (!isLayoutRtl()) {
+            return super.getCompoundPaddingLeft();
+        }
+        int padding = super.getCompoundPaddingLeft() + mSwitchWidth;
+        if (!TextUtils.isEmpty(getText())) {
+            padding += mSwitchPadding;
+        }
+        return padding;
+    }
+
+    @Override
     public int getCompoundPaddingRight() {
+        if (isLayoutRtl()) {
+            return super.getCompoundPaddingRight();
+        }
         int padding = super.getCompoundPaddingRight() + mSwitchWidth;
         if (!TextUtils.isEmpty(getText())) {
             padding += mSwitchPadding;
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 78e9453..b8ffe8d 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -739,11 +739,7 @@
         @Override
         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
             this.width = MATCH_PARENT;
-            if (a.hasValue(heightAttr)) {
-                this.height = a.getLayoutDimension(heightAttr, "layout_height");
-            } else {
-                this.height = WRAP_CONTENT;
-            }
+            this.height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
         }
     }
 
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 01c4c2c..fb548df 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -502,19 +502,8 @@
 
         @Override
         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
-            // We don't want to force users to specify a layout_width
-            if (a.hasValue(widthAttr)) {
-                width = a.getLayoutDimension(widthAttr, "layout_width");
-            } else {
-                width = MATCH_PARENT;
-            }
-
-            // We don't want to force users to specify a layout_height
-            if (a.hasValue(heightAttr)) {
-                height = a.getLayoutDimension(heightAttr, "layout_height");
-            } else {
-                height = WRAP_CONTENT;
-            }
+            width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
+            height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
         }
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 01617da..25f0131 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1542,7 +1542,6 @@
     /**
      * Returns the start padding of the view, plus space for the start
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingStart() {
         resolveDrawables();
@@ -1558,7 +1557,6 @@
     /**
      * Returns the end padding of the view, plus space for the end
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingEnd() {
         resolveDrawables();
@@ -1656,7 +1654,6 @@
     /**
      * Returns the total start padding of the view, including the start
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingStart() {
         return getCompoundPaddingStart();
@@ -1665,7 +1662,6 @@
     /**
      * Returns the total end padding of the view, including the end
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingEnd() {
         return getCompoundPaddingEnd();
@@ -1868,7 +1864,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     public void setCompoundDrawablesRelative(Drawable start, Drawable top,
                                      Drawable end, Drawable bottom) {
@@ -1990,7 +1985,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     @android.view.RemotableViewMethod
     public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
@@ -2014,7 +2008,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
             Drawable end, Drawable bottom) {
@@ -2061,7 +2054,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     public Drawable[] getCompoundDrawablesRelative() {
         final Drawables dr = mDrawables;
@@ -4586,23 +4578,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public int getResolvedLayoutDirection(Drawable who) {
-        if (who == null) return View.LAYOUT_DIRECTION_LTR;
-        if (mDrawables != null) {
-            final Drawables drawables = mDrawables;
-            if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
-                who == drawables.mDrawableTop || who == drawables.mDrawableBottom ||
-                who == drawables.mDrawableStart || who == drawables.mDrawableEnd) {
-                return getResolvedLayoutDirection();
-            }
-        }
-        return super.getResolvedLayoutDirection(who);
-    }
-
     @Override
     public boolean hasOverlappingRendering() {
         return (getBackground() != null || mText instanceof Spannable || hasSelection());
@@ -5634,7 +5609,6 @@
                       physicalWidth, false);
     }
 
-    /** @hide */
     @Override
     public void onResolvedLayoutDirectionReset() {
         if (mLayoutAlignment != null) {
@@ -8180,7 +8154,6 @@
         return mEditor.mInBatchEditControllers;
     }
 
-    /** @hide */
     @Override
     public void onResolvedTextDirectionChanged() {
         if (hasPasswordTransformationMethod()) {
@@ -8216,13 +8189,8 @@
         }
     }
 
-    /**
-     * Subclasses will need to override this method to implement their own way of resolving
-     * drawables depending on the layout direction.
-     *
-     * A call to the super method will be required from the subclasses implementation.
-     */
-    protected void resolveDrawables() {
+    @Override
+    public void onResolveDrawables(int layoutDirection) {
         // No need to resolve twice
         if (mResolvedDrawables) {
             return;
@@ -8238,7 +8206,7 @@
         }
 
         Drawables dr = mDrawables;
-        switch(getResolvedLayoutDirection()) {
+        switch(layoutDirection) {
             case LAYOUT_DIRECTION_RTL:
                 if (dr.mDrawableStart != null) {
                     dr.mDrawableRight = dr.mDrawableStart;
@@ -8270,9 +8238,25 @@
                 }
                 break;
         }
+        updateDrawablesLayoutDirection(dr, layoutDirection);
         mResolvedDrawables = true;
     }
 
+    private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
+        if (dr.mDrawableLeft != null) {
+            dr.mDrawableLeft.setLayoutDirection(layoutDirection);
+        }
+        if (dr.mDrawableRight != null) {
+            dr.mDrawableRight.setLayoutDirection(layoutDirection);
+        }
+        if (dr.mDrawableTop != null) {
+            dr.mDrawableTop.setLayoutDirection(layoutDirection);
+        }
+        if (dr.mDrawableBottom != null) {
+            dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+        }
+    }
+
     protected void resetResolvedDrawables() {
         mResolvedDrawables = false;
     }
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index fafc113..6fc0773 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -24,6 +24,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.util.LocaleUtil;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -33,6 +34,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
+import java.util.Locale;
+
 /**
  * A toast is a view containing a quick little message for the user.  The toast class
  * helps you create and show those.
@@ -371,7 +374,11 @@
                 handleHide();
                 mView = mNextView;
                 mWM = WindowManagerImpl.getDefault();
-                final int gravity = mGravity;
+                // We can resolve the Gravity here by using the Locale for getting
+                // the layout direction
+                final int layoutDirection = LocaleUtil.getLayoutDirectionFromLocale(
+                        Locale.getDefault());
+                final int gravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
                 mParams.gravity = gravity;
                 if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
                     mParams.horizontalWeight = 1.0f;
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index e707ea3..f7e5266 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -37,7 +37,11 @@
  * layout for this object.
  * 
  * @attr ref android.R.styleable#TwoLineListItem_mode
+ * 
+ * @deprecated This class can be implemented easily by apps using a {@link RelativeLayout}
+ * or a {@link LinearLayout}.
  */
+@Deprecated
 @Widget
 public class TwoLineListItem extends RelativeLayout {
 
diff --git a/core/java/android/widget/ValueEditor.java b/core/java/android/widget/ValueEditor.java
new file mode 100755
index 0000000..2b91abf
--- /dev/null
+++ b/core/java/android/widget/ValueEditor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.util.ValueModel;
+
+/**
+ * An interface for editors of simple values. Classes implementing this interface are normally
+ * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable
+ * user interface to display and edit values of the specified type. This interface is
+ * intended to describe editors for simple types, like {@code boolean}, {@code int} or
+ * {@code String}, where the values themselves are immutable.
+ * <p>
+ * For example, {@link android.widget.CheckBox CheckBox} implements
+ * this interface for the Boolean type as it is capable of providing an appropriate
+ * mechanism for displaying and changing the value of a Boolean property.
+ *
+ * @param <T> the value type that this editor supports
+ */
+public interface ValueEditor<T> {
+    /**
+     * Return the last value model that was set. If no value model has been set, the editor
+     * should return the value {@link android.util.ValueModel#EMPTY}.
+     *
+     * @return the value model
+     */
+    public ValueModel<T> getValueModel();
+
+    /**
+     * Sets the value model for this editor. When the value model is set, the editor should
+     * retrieve the value from the value model, using {@link android.util.ValueModel#get()},
+     * and set its internal state accordingly. Likewise, when the editor's internal state changes
+     * it should update the value model by calling  {@link android.util.ValueModel#set(T)}
+     * with the appropriate value.
+     *
+     * @param valueModel the new value model for this editor.
+     */
+    public void setValueModel(ValueModel<T> valueModel);
+}
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 02dc27b..a89c9c1 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -242,7 +242,7 @@
     private FrameLayout createContainer() {
         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         // Controls are positioned BOTTOM | CENTER with respect to the owner view.
-        lp.gravity = Gravity.TOP | Gravity.LEFT;
+        lp.gravity = Gravity.TOP | Gravity.START;
         lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE |
                 LayoutParams.FLAG_NOT_FOCUSABLE |
                 LayoutParams.FLAG_LAYOUT_NO_LIMITS |
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 6a0cd36..1a76461 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -58,14 +58,14 @@
     void noteBluetoothOff();
     void noteFullWifiLockAcquired(int uid);
     void noteFullWifiLockReleased(int uid);
-    void noteScanWifiLockAcquired(int uid);
-    void noteScanWifiLockReleased(int uid);
+    void noteWifiScanStarted(int uid);
+    void noteWifiScanStopped(int uid);
     void noteWifiMulticastEnabled(int uid);
     void noteWifiMulticastDisabled(int uid);
     void noteFullWifiLockAcquiredFromSource(in WorkSource ws);
     void noteFullWifiLockReleasedFromSource(in WorkSource ws);
-    void noteScanWifiLockAcquiredFromSource(in WorkSource ws);
-    void noteScanWifiLockReleasedFromSource(in WorkSource ws);
+    void noteWifiScanStartedFromSource(in WorkSource ws);
+    void noteWifiScanStoppedFromSource(in WorkSource ws);
     void noteWifiMulticastEnabledFromSource(in WorkSource ws);
     void noteWifiMulticastDisabledFromSource(in WorkSource ws);
     void noteNetworkInterfaceType(String iface, int type);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7334ac3..84fe8ce 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -76,6 +76,7 @@
     private int mIconDpi;
     private int mIconSize;
     private int mMaxColumns;
+    private int mLastSelected = GridView.INVALID_POSITION;
 
     private boolean mRegistered;
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -247,6 +248,7 @@
         if (mAlwaysUseOption) {
             final int checkedPos = mGrid.getCheckedItemPosition();
             final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+            mLastSelected = checkedPos;
             mAlwaysButton.setEnabled(enabled);
             mOnceButton.setEnabled(enabled);
             if (enabled) {
@@ -257,14 +259,15 @@
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        if (mAlwaysUseOption) {
-            final int checkedPos = mGrid.getCheckedItemPosition();
-            final boolean enabled = checkedPos != GridView.INVALID_POSITION;
-            mAlwaysButton.setEnabled(enabled);
-            mOnceButton.setEnabled(enabled);
-            if (enabled) {
+        final int checkedPos = mGrid.getCheckedItemPosition();
+        final boolean hasValidSelection = checkedPos != GridView.INVALID_POSITION;
+        if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
+            mAlwaysButton.setEnabled(hasValidSelection);
+            mOnceButton.setEnabled(hasValidSelection);
+            if (hasValidSelection) {
                 mGrid.smoothScrollToPosition(checkedPos);
             }
+            mLastSelected = checkedPos;
         } else {
             startSelected(position, false);
         }
@@ -371,7 +374,8 @@
 
     void showAppDetails(ResolveInfo ri) {
         Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
-                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
         startActivity(in);
     }
 
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
index 216d985..78b4466 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
@@ -24,6 +24,7 @@
 oneway interface IAppWidgetHost {
     void updateAppWidget(int appWidgetId, in RemoteViews views);
     void providerChanged(int appWidgetId, in AppWidgetProviderInfo info);
+    void providersChanged();
     void viewDataChanged(int appWidgetId, int viewId);
 }
 
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index f41fcc6..650681a 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -111,16 +111,22 @@
     
     public void onBeginPackageChanges() {
     }
-    
+
+    /**
+     * Called when a package is really added (and not replaced).
+     */
     public void onPackageAdded(String packageName, int uid) {
     }
-    
+
+    /**
+     * Called when a package is really removed (and not replaced).
+     */
     public void onPackageRemoved(String packageName, int uid) {
     }
-    
+
     public void onPackageUpdateStarted(String packageName, int uid) {
     }
-    
+
     public void onPackageUpdateFinished(String packageName, int uid) {
     }
     
@@ -144,10 +150,16 @@
     public static final int PACKAGE_UPDATING = 1;
     public static final int PACKAGE_TEMPORARY_CHANGE = 2;
     public static final int PACKAGE_PERMANENT_CHANGE = 3;
-    
+
+    /**
+     * Called when a package disappears for any reason.
+     */
     public void onPackageDisappeared(String packageName, int reason) {
     }
-    
+
+    /**
+     * Called when a package appears for any reason.
+     */
     public void onPackageAppeared(String packageName, int reason) {
     }
     
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
new file mode 100644
index 0000000..154b16b
--- /dev/null
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import java.nio.charset.Charsets;
+
+/**
+ * Parcel-like entity class for VPN profiles. To keep things simple, all
+ * fields are package private. Methods are provided for serialization, so
+ * storage can be implemented easily. Two rules are set for this class.
+ * First, all fields must be kept non-null. Second, always make a copy
+ * using clone() before modifying.
+ *
+ * @hide
+ */
+public class VpnProfile implements Cloneable {
+    // Match these constants with R.array.vpn_types.
+    public static final int TYPE_PPTP = 0;
+    public static final int TYPE_L2TP_IPSEC_PSK = 1;
+    public static final int TYPE_L2TP_IPSEC_RSA = 2;
+    public static final int TYPE_IPSEC_XAUTH_PSK = 3;
+    public static final int TYPE_IPSEC_XAUTH_RSA = 4;
+    public static final int TYPE_IPSEC_HYBRID_RSA = 5;
+    public static final int TYPE_MAX = 5;
+
+    // Entity fields.
+    public final String key;           // -1
+    public String name = "";           // 0
+    public int type = TYPE_PPTP;       // 1
+    public String server = "";         // 2
+    public String username = "";       // 3
+    public String password = "";       // 4
+    public String dnsServers = "";     // 5
+    public String searchDomains = "";  // 6
+    public String routes = "";         // 7
+    public boolean mppe = true;        // 8
+    public String l2tpSecret = "";     // 9
+    public String ipsecIdentifier = "";// 10
+    public String ipsecSecret = "";    // 11
+    public String ipsecUserCert = "";  // 12
+    public String ipsecCaCert = "";    // 13
+    public String ipsecServerCert = "";// 14
+
+    // Helper fields.
+    public boolean saveLogin = false;
+
+    public VpnProfile(String key) {
+        this.key = key;
+    }
+
+    public static VpnProfile decode(String key, byte[] value) {
+        try {
+            if (key == null) {
+                return null;
+            }
+
+            String[] values = new String(value, Charsets.UTF_8).split("\0", -1);
+            // There can be 14 or 15 values in ICS MR1.
+            if (values.length < 14 || values.length > 15) {
+                return null;
+            }
+
+            VpnProfile profile = new VpnProfile(key);
+            profile.name = values[0];
+            profile.type = Integer.valueOf(values[1]);
+            if (profile.type < 0 || profile.type > TYPE_MAX) {
+                return null;
+            }
+            profile.server = values[2];
+            profile.username = values[3];
+            profile.password = values[4];
+            profile.dnsServers = values[5];
+            profile.searchDomains = values[6];
+            profile.routes = values[7];
+            profile.mppe = Boolean.valueOf(values[8]);
+            profile.l2tpSecret = values[9];
+            profile.ipsecIdentifier = values[10];
+            profile.ipsecSecret = values[11];
+            profile.ipsecUserCert = values[12];
+            profile.ipsecCaCert = values[13];
+            profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
+
+            profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
+            return profile;
+        } catch (Exception e) {
+            // ignore
+        }
+        return null;
+    }
+
+    public byte[] encode() {
+        StringBuilder builder = new StringBuilder(name);
+        builder.append('\0').append(type);
+        builder.append('\0').append(server);
+        builder.append('\0').append(saveLogin ? username : "");
+        builder.append('\0').append(saveLogin ? password : "");
+        builder.append('\0').append(dnsServers);
+        builder.append('\0').append(searchDomains);
+        builder.append('\0').append(routes);
+        builder.append('\0').append(mppe);
+        builder.append('\0').append(l2tpSecret);
+        builder.append('\0').append(ipsecIdentifier);
+        builder.append('\0').append(ipsecSecret);
+        builder.append('\0').append(ipsecUserCert);
+        builder.append('\0').append(ipsecCaCert);
+        builder.append('\0').append(ipsecServerCert);
+        return builder.toString().getBytes(Charsets.UTF_8);
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5157385..42bc14d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -159,8 +159,8 @@
             = new SparseArray<ArrayList<StopwatchTimer>>();
     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
-    final ArrayList<StopwatchTimer> mScanWifiLockTimers = new ArrayList<StopwatchTimer>();
     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
+    final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>();
 
     // Last partial timers we use for distributing CPU usage.
     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
@@ -320,6 +320,18 @@
         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
     };
 
+    private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
+        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE|
+                              Process.PROC_OUT_LONG,                  // 1: count
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE
+                             |Process.PROC_OUT_LONG,                  // 6: totalTime
+    };
+
     private final String[] mProcWakelocksName = new String[3];
     private final long[] mProcWakelocksData = new long[3];
 
@@ -1028,34 +1040,44 @@
 
     private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
 
+        FileInputStream is;
         byte[] buffer = new byte[8192];
         int len;
+        boolean wakeup_sources = false;
 
         try {
-            FileInputStream is = new FileInputStream("/proc/wakelocks");
-            len = is.read(buffer);
-            is.close();
-
-            if (len > 0) {
-                int i;
-                for (i=0; i<len; i++) {
-                    if (buffer[i] == '\0') {
-                        len = i;
-                        break;
-                    }
+            try {
+                is = new FileInputStream("/proc/wakelocks");
+            } catch (java.io.FileNotFoundException e) {
+                try {
+                    is = new FileInputStream("/d/wakeup_sources");
+                    wakeup_sources = true;
+                } catch (java.io.FileNotFoundException e2) {
+                    return null;
                 }
             }
-        } catch (java.io.FileNotFoundException e) {
-            return null;
+
+            len = is.read(buffer);
+            is.close();
         } catch (java.io.IOException e) {
             return null;
         }
 
-        return parseProcWakelocks(buffer, len);
+        if (len > 0) {
+            int i;
+            for (i=0; i<len; i++) {
+                if (buffer[i] == '\0') {
+                    len = i;
+                    break;
+                }
+            }
+        }
+
+        return parseProcWakelocks(buffer, len, wakeup_sources);
     }
 
     private final Map<String, KernelWakelockStats> parseProcWakelocks(
-            byte[] wlBuffer, int len) {
+            byte[] wlBuffer, int len, boolean wakeup_sources) {
         String name;
         int count;
         long totalTime;
@@ -1092,12 +1114,20 @@
                     if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
                 }
                 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
-                        PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null);
+                        wakeup_sources ? WAKEUP_SOURCES_FORMAT :
+                                         PROC_WAKELOCKS_FORMAT,
+                        nameStringArray, wlData, null);
 
                 name = nameStringArray[0];
                 count = (int) wlData[1];
-                // convert nanoseconds to microseconds with rounding.
-                totalTime = (wlData[2] + 500) / 1000;
+
+                if (wakeup_sources) {
+                        // convert milliseconds to microseconds
+                        totalTime = wlData[2] * 1000;
+                } else {
+                        // convert nanoseconds to microseconds with rounding.
+                        totalTime = (wlData[2] + 500) / 1000;
+                }
 
                 if (parsed && name.length() > 0) {
                     if (!m.containsKey(name)) {
@@ -2174,28 +2204,28 @@
         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
     }
 
-    int mWifiScanLockNesting = 0;
+    int mWifiScanNesting = 0;
 
-    public void noteScanWifiLockAcquiredLocked(int uid) {
-        if (mWifiScanLockNesting == 0) {
-            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock on to: "
+    public void noteWifiScanStartedLocked(int uid) {
+        if (mWifiScanNesting == 0) {
+            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
         }
-        mWifiScanLockNesting++;
-        getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
+        mWifiScanNesting++;
+        getUidStatsLocked(uid).noteWifiScanStartedLocked();
     }
 
-    public void noteScanWifiLockReleasedLocked(int uid) {
-        mWifiScanLockNesting--;
-        if (mWifiScanLockNesting == 0) {
-            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock off to: "
+    public void noteWifiScanStoppedLocked(int uid) {
+        mWifiScanNesting--;
+        if (mWifiScanNesting == 0) {
+            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
         }
-        getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
+        getUidStatsLocked(uid).noteWifiScanStoppedLocked();
     }
 
     int mWifiMulticastNesting = 0;
@@ -2236,17 +2266,17 @@
         }
     }
 
-    public void noteScanWifiLockAcquiredFromSourceLocked(WorkSource ws) {
+    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteScanWifiLockAcquiredLocked(ws.get(i));
+            noteWifiScanStartedLocked(ws.get(i));
         }
     }
 
-    public void noteScanWifiLockReleasedFromSourceLocked(WorkSource ws) {
+    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteScanWifiLockReleasedLocked(ws.get(i));
+            noteWifiScanStoppedLocked(ws.get(i));
         }
     }
 
@@ -2360,8 +2390,8 @@
         boolean mFullWifiLockOut;
         StopwatchTimer mFullWifiLockTimer;
 
-        boolean mScanWifiLockOut;
-        StopwatchTimer mScanWifiLockTimer;
+        boolean mWifiScanStarted;
+        StopwatchTimer mWifiScanTimer;
 
         boolean mWifiMulticastEnabled;
         StopwatchTimer mWifiMulticastTimer;
@@ -2405,8 +2435,8 @@
                     mWifiRunningTimers, mUnpluggables);
             mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
                     mFullWifiLockTimers, mUnpluggables);
-            mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
-                    mScanWifiLockTimers, mUnpluggables);
+            mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+                    mWifiScanTimers, mUnpluggables);
             mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
                     mWifiMulticastTimers, mUnpluggables);
             mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
@@ -2518,22 +2548,22 @@
         }
 
         @Override
-        public void noteScanWifiLockAcquiredLocked() {
-            if (!mScanWifiLockOut) {
-                mScanWifiLockOut = true;
-                if (mScanWifiLockTimer == null) {
-                    mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
-                            mScanWifiLockTimers, mUnpluggables);
+        public void noteWifiScanStartedLocked() {
+            if (!mWifiScanStarted) {
+                mWifiScanStarted = true;
+                if (mWifiScanTimer == null) {
+                    mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+                            mWifiScanTimers, mUnpluggables);
                 }
-                mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
+                mWifiScanTimer.startRunningLocked(BatteryStatsImpl.this);
             }
         }
 
         @Override
-        public void noteScanWifiLockReleasedLocked() {
-            if (mScanWifiLockOut) {
-                mScanWifiLockOut = false;
-                mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
+        public void noteWifiScanStoppedLocked() {
+            if (mWifiScanStarted) {
+                mWifiScanStarted = false;
+                mWifiScanTimer.stopRunningLocked(BatteryStatsImpl.this);
             }
         }
 
@@ -2614,11 +2644,11 @@
         }
 
         @Override
-        public long getScanWifiLockTime(long batteryRealtime, int which) {
-            if (mScanWifiLockTimer == null) {
+        public long getWifiScanTime(long batteryRealtime, int which) {
+            if (mWifiScanTimer == null) {
                 return 0;
             }
-            return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mWifiScanTimer.getTotalTimeLocked(batteryRealtime, which);
         }
 
         @Override
@@ -2698,9 +2728,9 @@
                 active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false);
                 active |= mFullWifiLockOut;
             }
-            if (mScanWifiLockTimer != null) {
-                active |= !mScanWifiLockTimer.reset(BatteryStatsImpl.this, false);
-                active |= mScanWifiLockOut;
+            if (mWifiScanTimer != null) {
+                active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false);
+                active |= mWifiScanStarted;
             }
             if (mWifiMulticastTimer != null) {
                 active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false);
@@ -2791,8 +2821,8 @@
                 if (mFullWifiLockTimer != null) {
                     mFullWifiLockTimer.detach();
                 }
-                if (mScanWifiLockTimer != null) {
-                    mScanWifiLockTimer.detach();
+                if (mWifiScanTimer != null) {
+                    mWifiScanTimer.detach();
                 }
                 if (mWifiMulticastTimer != null) {
                     mWifiMulticastTimer.detach();
@@ -2860,9 +2890,9 @@
             } else {
                 out.writeInt(0);
             }
-            if (mScanWifiLockTimer != null) {
+            if (mWifiScanTimer != null) {
                 out.writeInt(1);
-                mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
+                mWifiScanTimer.writeToParcel(out, batteryRealtime);
             } else {
                 out.writeInt(0);
             }
@@ -2954,12 +2984,12 @@
             } else {
                 mFullWifiLockTimer = null;
             }
-            mScanWifiLockOut = false;
+            mWifiScanStarted = false;
             if (in.readInt() != 0) {
-                mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
-                        mScanWifiLockTimers, mUnpluggables, in);
+                mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+                        mWifiScanTimers, mUnpluggables, in);
             } else {
-                mScanWifiLockTimer = null;
+                mWifiScanTimer = null;
             }
             mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
@@ -5118,9 +5148,9 @@
             if (in.readInt() != 0) {
                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
             }
-            u.mScanWifiLockOut = false;
+            u.mWifiScanStarted = false;
             if (in.readInt() != 0) {
-                u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
+                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
             }
             u.mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
@@ -5310,9 +5340,9 @@
             } else {
                 out.writeInt(0);
             }
-            if (u.mScanWifiLockTimer != null) {
+            if (u.mWifiScanTimer != null) {
                 out.writeInt(1);
-                u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL);
             } else {
                 out.writeInt(0);
             }
@@ -5537,7 +5567,7 @@
         mWindowTimers.clear();
         mWifiRunningTimers.clear();
         mFullWifiLockTimers.clear();
-        mScanWifiLockTimers.clear();
+        mWifiScanTimers.clear();
         mWifiMulticastTimers.clear();
 
         sNumSpeedSteps = in.readInt();
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 4c34d73..ac1d594 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -28,11 +28,12 @@
 public class BaseIWindow extends IWindow.Stub {
     private IWindowSession mSession;
     public int mSeq;
-    
+
     public void setSession(IWindowSession session) {
         mSession = session;
     }
-    
+
+    @Override
     public void resized(int w, int h, Rect contentInsets,
             Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
         if (reportDraw) {
@@ -43,24 +44,35 @@
         }
     }
 
+    @Override
+    public void moved(int newX, int newY) {
+    }
+
+    @Override
     public void dispatchAppVisibility(boolean visible) {
     }
 
+    @Override
     public void dispatchGetNewSurface() {
     }
 
+    @Override
     public void dispatchScreenState(boolean on) {
     }
 
+    @Override
     public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
     }
 
+    @Override
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
     }
-    
+
+    @Override
     public void closeSystemDialogs(String reason) {
     }
-    
+
+    @Override
     public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
         if (sync) {
             try {
@@ -70,14 +82,17 @@
         }
     }
 
+    @Override
     public void dispatchDragEvent(DragEvent event) {
     }
 
+    @Override
     public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
             int localValue, int localChanges) {
         mSeq = seq;
     }
 
+    @Override
     public void dispatchWallpaperCommand(String action, int x, int y,
             int z, Bundle extras, boolean sync) {
         if (sync) {
@@ -88,6 +103,7 @@
         }
     }
 
+    @Override
     public void doneAnimating() {
     }
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 449194b..671badb 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -209,7 +209,7 @@
         Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
         if (midy < displayFrame.height()) {
             // Show along the top; follow action buttons
-            cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
+            cheatSheet.setGravity(Gravity.TOP | Gravity.END,
                     screenWidth - screenPos[0] - width / 2, height);
         } else {
             // Show along the bottom center
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index f54575b..511417e 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -489,8 +489,10 @@
 
     @Override
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
-        if (p instanceof LayoutParams) {
-            LayoutParams result = new LayoutParams((LayoutParams) p);
+        if (p != null) {
+            final LayoutParams result = p instanceof LayoutParams
+                    ? new LayoutParams((LayoutParams) p)
+                    : new LayoutParams(p);
             if (result.gravity <= Gravity.NO_GRAVITY) {
                 result.gravity = Gravity.CENTER_VERTICAL;
             }
@@ -563,6 +565,10 @@
             super(c, attrs);
         }
 
+        public LayoutParams(ViewGroup.LayoutParams other) {
+            super(other);
+        }
+
         public LayoutParams(LayoutParams other) {
             super((LinearLayout.LayoutParams) other);
             isOverflowButton = other.isOverflowButton;
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index a743cfa..c7c8571 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -282,7 +282,7 @@
         getLineBounds(0, tmpRect);
         mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
         final int layoutDirection = getResolvedLayoutDirection();
-        Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.LEFT, mIcon.getIntrinsicWidth(), mIcon
+        Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.START, mIcon.getIntrinsicWidth(), mIcon
                 .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput,
                 layoutDirection);
         mIcon.setBounds(mPositionIconOutput);
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 25a9c54..860a8d9 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -219,24 +219,22 @@
         return Math.max(0, availableWidth);
     }
 
-    protected int positionChild(View child, int x, int y, int contentHeight) {
-        int childWidth = child.getMeasuredWidth();
-        int childHeight = child.getMeasuredHeight();
-        int childTop = y + (contentHeight - childHeight) / 2;
-
-        child.layout(x, childTop, x + childWidth, childTop + childHeight);
-
-        return childWidth;
+    static protected int next(int x, int val, boolean isRtl) {
+        return isRtl ? x - val : x + val;
     }
 
-    protected int positionChildInverse(View child, int x, int y, int contentHeight) {
+    protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
         int childWidth = child.getMeasuredWidth();
         int childHeight = child.getMeasuredHeight();
         int childTop = y + (contentHeight - childHeight) / 2;
 
-        child.layout(x - childWidth, childTop, x, childTop + childHeight);
+        if (reverse) {
+            child.layout(x - childWidth, childTop, x, childTop + childHeight);
+        } else {
+            child.layout(x, childTop, x + childWidth, childTop + childHeight);
+        }
 
-        return childWidth;
+        return  (reverse ? -childWidth : childWidth);
     }
 
     protected class VisibilityAnimListener implements Animator.AnimatorListener {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 16f08f5..8bc1081 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -454,15 +454,18 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int x = getPaddingLeft();
+        final boolean isLayoutRtl = isLayoutRtl();
+        int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
         final int y = getPaddingTop();
         final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
         
         if (mClose != null && mClose.getVisibility() != GONE) {
             MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams();
-            x += lp.leftMargin;
-            x += positionChild(mClose, x, y, contentHeight);
-            x += lp.rightMargin;
+            final int startMargin = (isLayoutRtl ? lp.rightMargin : lp.leftMargin);
+            final int endMargin = (isLayoutRtl ? lp.leftMargin : lp.rightMargin);
+            x = next(x, startMargin, isLayoutRtl);
+            x += positionChild(mClose, x, y, contentHeight, isLayoutRtl);
+            x = next(x, endMargin, isLayoutRtl);
 
             if (mAnimateInOnLayout) {
                 mAnimationMode = ANIMATE_IN;
@@ -473,17 +476,17 @@
         }
 
         if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) {
-            x += positionChild(mTitleLayout, x, y, contentHeight);
+            x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
         }
         
         if (mCustomView != null) {
-            x += positionChild(mCustomView, x, y, contentHeight);
+            x += positionChild(mCustomView, x, y, contentHeight, isLayoutRtl);
         }
-        
-        x = r - l - getPaddingRight();
+
+        x = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
 
         if (mMenuView != null) {
-            x -= positionChildInverse(mMenuView, x, y, contentHeight);
+            x += positionChild(mMenuView, x, y, contentHeight, !isLayoutRtl);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 450f418..8ff39d69 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -84,7 +84,7 @@
             ActionBar.DISPLAY_SHOW_CUSTOM |
             ActionBar.DISPLAY_SHOW_TITLE;
 
-    private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
+    private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
     
     private int mNavigationMode;
     private int mDisplayOptions = -1;
@@ -872,7 +872,7 @@
             }
             homeLayout.measure(homeWidthSpec,
                     MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset();
+            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
             availableWidth = Math.max(0, availableWidth - homeWidth);
             leftOfCenter = Math.max(0, availableWidth - homeWidth);
         }
@@ -1010,8 +1010,6 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int x = getPaddingLeft();
-        final int y = getPaddingTop();
         final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
 
         if (contentHeight <= 0) {
@@ -1019,13 +1017,23 @@
             return;
         }
 
+        final boolean isLayoutRtl = isLayoutRtl();
+        final int direction = isLayoutRtl ? +1 : -1;
+        int menuStart = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
+        // In LTR mode, we start from left padding and go to the right; in RTL mode, we start
+        // from the padding right and go to the left (in reverse way)
+        int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
+        final int y = getPaddingTop();
+
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
         boolean needsTouchDelegate = false;
         int homeSlop = mMaxHomeSlop;
         int homeRight = 0;
         if (homeLayout.getVisibility() != GONE) {
-            final int leftOffset = homeLayout.getLeftOffset();
-            x += positionChild(homeLayout, x + leftOffset, y, contentHeight) + leftOffset;
+            final int startOffset = homeLayout.getStartOffset();
+            x += positionChild(homeLayout,
+                            next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
+            x = next(x, startOffset, isLayoutRtl);
             needsTouchDelegate = homeLayout == mHomeLayout;
             homeRight = x;
         }
@@ -1034,7 +1042,7 @@
             final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
             if (showTitle) {
-                x += positionChild(mTitleLayout, x, y, contentHeight);
+                x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
             }
 
             switch (mNavigationMode) {
@@ -1042,31 +1050,34 @@
                     break;
                 case ActionBar.NAVIGATION_MODE_LIST:
                     if (mListNavLayout != null) {
-                        if (showTitle) x += mItemPadding;
+                        if (showTitle) {
+                            x = next(x, mItemPadding, isLayoutRtl);
+                        }
                         homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
-                        x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
+                        x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
+                        x = next(x, mItemPadding, isLayoutRtl);
                     }
                     break;
                 case ActionBar.NAVIGATION_MODE_TABS:
                     if (mTabScrollView != null) {
-                        if (showTitle) x += mItemPadding;
+                        if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
                         homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
-                        x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
+                        x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
+                        x = next(x, mItemPadding, isLayoutRtl);
                     }
                     break;
             }
         }
 
-        int menuLeft = r - l - getPaddingRight();
         if (mMenuView != null && mMenuView.getParent() == this) {
-            positionChildInverse(mMenuView, menuLeft, y, contentHeight);
-            menuLeft -= mMenuView.getMeasuredWidth();
+            positionChild(mMenuView, menuStart, y, contentHeight, !isLayoutRtl);
+            menuStart += direction * mMenuView.getMeasuredWidth();
         }
 
         if (mIndeterminateProgressView != null &&
                 mIndeterminateProgressView.getVisibility() != GONE) {
-            positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight);
-            menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
+            positionChild(mIndeterminateProgressView, menuStart, y, contentHeight, !isLayoutRtl);
+            menuStart += direction * mIndeterminateProgressView.getMeasuredWidth();
         }
 
         View customView = null;
@@ -1077,51 +1088,64 @@
             customView = mCustomNavView;
         }
         if (customView != null) {
+            final int resolvedLayoutDirection = getResolvedLayoutDirection();
             ViewGroup.LayoutParams lp = customView.getLayoutParams();
+            lp.onResolveLayoutDirection(resolvedLayoutDirection);
             final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
                     (ActionBar.LayoutParams) lp : null;
-
             final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
             final int navWidth = customView.getMeasuredWidth();
 
             int topMargin = 0;
             int bottomMargin = 0;
             if (ablp != null) {
-                x += ablp.leftMargin;
-                menuLeft -= ablp.rightMargin;
+                x = next(x, ablp.getMarginStart(), isLayoutRtl);
+                menuStart += direction * ablp.getMarginEnd();
                 topMargin = ablp.topMargin;
                 bottomMargin = ablp.bottomMargin;
             }
 
-            int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+            int hgravity = gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
             // See if we actually have room to truly center; if not push against left or right.
             if (hgravity == Gravity.CENTER_HORIZONTAL) {
                 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
-                if (centeredLeft < x) {
-                    hgravity = Gravity.LEFT;
-                } else if (centeredLeft + navWidth > menuLeft) {
-                    hgravity = Gravity.RIGHT;
+                if (isLayoutRtl) {
+                    final int centeredStart = centeredLeft + navWidth;
+                    final int centeredEnd = centeredLeft;
+                    if (centeredStart > x) {
+                        hgravity = Gravity.RIGHT;
+                    } else if (centeredEnd < menuStart) {
+                        hgravity = Gravity.LEFT;
+                    }
+                } else {
+                    final int centeredStart = centeredLeft;
+                    final int centeredEnd = centeredLeft + navWidth;
+                    if (centeredStart < x) {
+                        hgravity = Gravity.LEFT;
+                    } else if (centeredEnd > menuStart) {
+                        hgravity = Gravity.RIGHT;
+                    }
                 }
-            } else if (gravity == -1) {
-                hgravity = Gravity.LEFT;
+            } else if (gravity == Gravity.NO_GRAVITY) {
+                hgravity = Gravity.START;
             }
 
             int xpos = 0;
-            switch (hgravity) {
+            switch (Gravity.getAbsoluteGravity(hgravity, resolvedLayoutDirection)) {
                 case Gravity.CENTER_HORIZONTAL:
                     xpos = ((mRight - mLeft) - navWidth) / 2;
                     break;
                 case Gravity.LEFT:
-                    xpos = x;
+                    xpos = isLayoutRtl ? menuStart : x;
                     break;
                 case Gravity.RIGHT:
-                    xpos = menuLeft - navWidth;
+                    xpos = isLayoutRtl ? x - navWidth : menuStart - navWidth;
                     break;
             }
 
             int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
 
-            if (gravity == -1) {
+            if (gravity == Gravity.NO_GRAVITY) {
                 vgravity = Gravity.CENTER_VERTICAL;
             }
 
@@ -1144,7 +1168,7 @@
             customView.layout(xpos, ypos, xpos + customWidth,
                     ypos + customView.getMeasuredHeight());
             homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
-            x += customWidth;
+            x = next(x, customWidth, isLayoutRtl);
         }
 
         if (mProgressView != null) {
@@ -1290,7 +1314,7 @@
             mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
         }
 
-        public int getLeftOffset() {
+        public int getStartOffset() {
             return mUpView.getVisibility() == GONE ? mUpWidth : 0;
         }
 
@@ -1340,25 +1364,51 @@
         @Override
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
             final int vCenter = (b - t) / 2;
-            int width = r - l;
+            final boolean isLayoutRtl = isLayoutRtl();
+            final int layoutDirection = getResolvedLayoutDirection();
+            final int width = getWidth();
             int upOffset = 0;
             if (mUpView.getVisibility() != GONE) {
                 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
+                upLp.onResolveLayoutDirection(layoutDirection);
                 final int upHeight = mUpView.getMeasuredHeight();
                 final int upWidth = mUpView.getMeasuredWidth();
-                final int upTop = vCenter - upHeight / 2;
-                mUpView.layout(0, upTop, upWidth, upTop + upHeight);
                 upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
-                width -= upOffset;
-                l += upOffset;
+                final int upTop = vCenter - upHeight / 2;
+                final int upBottom = upTop + upHeight;
+                final int upRight;
+                final int upLeft;
+                if (isLayoutRtl) {
+                    upRight = width;
+                    upLeft = upRight - upWidth;
+                    r -= upOffset;
+                } else {
+                    upRight = upWidth;
+                    upLeft = 0;
+                    l += upOffset;
+                }
+                mUpView.layout(upLeft, upTop, upRight, upBottom);
             }
+
             final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
+            iconLp.onResolveLayoutDirection(layoutDirection);
             final int iconHeight = mIconView.getMeasuredHeight();
             final int iconWidth = mIconView.getMeasuredWidth();
             final int hCenter = (r - l) / 2;
-            final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2);
             final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
-            mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
+            final int iconBottom = iconTop + iconHeight;
+            final int iconLeft;
+            final int iconRight;
+            int marginStart = iconLp.getMarginStart();
+            final int delta = Math.max(marginStart, hCenter - iconWidth / 2);
+            if (isLayoutRtl) {
+                iconRight = width - upOffset - delta;
+                iconLeft = iconRight - iconWidth;
+            } else {
+                iconLeft = upOffset + delta;
+                iconRight = iconLeft + iconWidth;
+            }
+            mIconView.layout(iconLeft, iconTop, iconRight, iconBottom);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
index 24c7161..2fb81ac 100644
--- a/core/java/com/android/internal/widget/LockSettingsService.java
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -24,6 +24,7 @@
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Binder;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.os.UserId;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
@@ -303,12 +304,15 @@
     }
 
     private void writeToDb(String key, String value, int userId) {
+        writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
+    }
+
+    private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
         ContentValues cv = new ContentValues();
         cv.put(COLUMN_KEY, key);
         cv.put(COLUMN_USERID, userId);
         cv.put(COLUMN_VALUE, value);
 
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {
             db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
@@ -359,6 +363,16 @@
         @Override
         public void onCreate(SQLiteDatabase db) {
             createTable(db);
+            initializeDefaults(db);
+        }
+
+        private void initializeDefaults(SQLiteDatabase db) {
+            // Get the lockscreen default from a system property, if available
+            boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
+                    false);
+            if (lockScreenDisable) {
+                writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
+            }
         }
 
         @Override
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 83ac896..08d9f49 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -363,7 +363,7 @@
             mTab = tab;
 
             if (forList) {
-                setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+                setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
             }
 
             update();
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
index e113dd8..e898aa4 100644
--- a/core/java/com/android/internal/widget/TextProgressBar.java
+++ b/core/java/com/android/internal/widget/TextProgressBar.java
@@ -155,7 +155,7 @@
             // Calculate any adjustment based on gravity
             int adjustLeft = 0;
             int textWidth = mChronometer.getWidth();
-            if (mChronometerGravity == Gravity.RIGHT) {
+            if (mChronometerGravity == Gravity.END) {
                 adjustLeft = -textWidth;
             } else if (mChronometerGravity == Gravity.CENTER_HORIZONTAL) {
                 adjustLeft = -(textWidth / 2);
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
index 4e60b75..421e247 100644
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -214,8 +214,8 @@
                 mVibrationDuration);
         mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
                 mFeedbackCount);
-        mHandleDrawable = new TargetDrawable(res,
-                a.peekValue(R.styleable.GlowPadView_handleDrawable).resourceId);
+        TypedValue handle = a.peekValue(R.styleable.GlowPadView_handleDrawable);
+        mHandleDrawable = new TargetDrawable(res, handle != null ? handle.resourceId : 0);
         mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
         mOuterRing = new TargetDrawable(res,
                 getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
@@ -717,7 +717,7 @@
         startBackgroundAnimation(0, 0.0f);
         stopAndHideWaveAnimation();
         hideTargets(animate, false);
-        hideGlow(0, 0, 1.0f, null);
+        hideGlow(0, 0, 0.0f, null);
         Tweener.reset();
     }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index b5a2f98..e429ffc 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -32,6 +32,7 @@
 	com_google_android_gles_jni_EGLImpl.cpp \
 	com_google_android_gles_jni_GLImpl.cpp.arm \
 	android_app_NativeActivity.cpp \
+	android_opengl_EGL14.cpp \
 	android_opengl_GLES10.cpp \
 	android_opengl_GLES10Ext.cpp \
 	android_opengl_GLES11.cpp \
@@ -137,14 +138,6 @@
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
-	android_bluetooth_HeadsetBase.cpp \
-	android_bluetooth_common.cpp \
-	android_bluetooth_BluetoothAudioGateway.cpp \
-	android_bluetooth_BluetoothSocket.cpp \
-	android_bluetooth_c.c \
-	android_server_BluetoothService.cpp \
-	android_server_BluetoothEventLoop.cpp \
-	android_server_BluetoothA2dpService.cpp \
 	android_server_NetworkManagementSocketTagger.cpp \
 	android_server_Watchdog.cpp \
 	android_ddm_DdmHandleNativeHeap.cpp \
@@ -170,6 +163,7 @@
 	external/skia/include/core \
 	external/skia/include/effects \
 	external/skia/include/images \
+	external/skia/include/ports \
 	external/skia/src/ports \
 	external/skia/include/utils \
 	external/sqlite/dist \
@@ -234,7 +228,6 @@
 	external/dbus \
 	system/bluetooth/bluez-clean-headers
 LOCAL_CFLAGS += -DHAVE_BLUETOOTH
-LOCAL_SHARED_LIBRARIES += libbluedroid libdbus
 endif
 
 LOCAL_SHARED_LIBRARIES += \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7a23747..f0dd321 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -68,6 +68,7 @@
 
 extern int register_com_google_android_gles_jni_EGLImpl(JNIEnv* env);
 extern int register_com_google_android_gles_jni_GLImpl(JNIEnv* env);
+extern int register_android_opengl_jni_EGL14(JNIEnv* env);
 extern int register_android_opengl_jni_GLES10(JNIEnv* env);
 extern int register_android_opengl_jni_GLES10Ext(JNIEnv* env);
 extern int register_android_opengl_jni_GLES11(JNIEnv* env);
@@ -149,12 +150,6 @@
 extern int register_android_text_AndroidCharacter(JNIEnv *env);
 extern int register_android_text_AndroidBidi(JNIEnv *env);
 extern int register_android_opengl_classes(JNIEnv *env);
-extern int register_android_bluetooth_HeadsetBase(JNIEnv* env);
-extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env);
-extern int register_android_bluetooth_BluetoothSocket(JNIEnv *env);
-extern int register_android_server_BluetoothService(JNIEnv* env);
-extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
-extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
 extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
 extern int register_android_server_Watchdog(JNIEnv* env);
 extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
@@ -1105,6 +1100,7 @@
     REG_JNI(register_android_view_TextureView),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
     REG_JNI(register_com_google_android_gles_jni_GLImpl),
+    REG_JNI(register_android_opengl_jni_EGL14),
     REG_JNI(register_android_opengl_jni_GLES10),
     REG_JNI(register_android_opengl_jni_GLES10Ext),
     REG_JNI(register_android_opengl_jni_GLES11),
@@ -1170,12 +1166,6 @@
     REG_JNI(register_android_media_ToneGenerator),
 
     REG_JNI(register_android_opengl_classes),
-    REG_JNI(register_android_bluetooth_HeadsetBase),
-    REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
-    REG_JNI(register_android_bluetooth_BluetoothSocket),
-    REG_JNI(register_android_server_BluetoothService),
-    REG_JNI(register_android_server_BluetoothEventLoop),
-    REG_JNI(register_android_server_BluetoothA2dpService),
     REG_JNI(register_android_server_NetworkManagementSocketTagger),
     REG_JNI(register_android_server_Watchdog),
     REG_JNI(register_android_ddm_DdmHandleNativeHeap),
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 6b74705..5c27602 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -766,15 +766,64 @@
         if (value == NULL) {
             return;
         }
-        doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), x, y, flags, paint);
+        SkPaint::Align align = paint->getTextAlign();
+        if (align == SkPaint::kCenter_Align) {
+            x -= 0.5 * value->getTotalAdvance();
+        } else if (align == SkPaint::kRight_Align) {
+            x -= value->getTotalAdvance();
+        }
+        paint->setTextAlign(SkPaint::kLeft_Align);
+        doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
+        doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
+        paint->setTextAlign(align);
     }
 
+// Same values used by Skia
+#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
+#define kStdUnderline_Offset    (1.0f / 9.0f)
+#define kStdUnderline_Thickness (1.0f / 18.0f)
+
+static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
+    uint32_t flags = paint->getFlags();
+    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+        SkScalar left = SkFloatToScalar(x);
+        SkScalar right = SkFloatToScalar(x + length);
+        float textSize = paint->getTextSize();
+        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+        if (flags & SkPaint::kUnderlineText_Flag) {
+            SkScalar top = SkFloatToScalar(y + textSize * kStdUnderline_Offset
+                    - 0.5f * strokeWidth);
+            SkScalar bottom = SkFloatToScalar(y + textSize * kStdUnderline_Offset
+                    + 0.5f * strokeWidth);
+            canvas->drawRectCoords(left, top, right, bottom, *paint);
+        }
+        if (flags & SkPaint::kStrikeThruText_Flag) {
+            SkScalar top = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
+                    - 0.5f * strokeWidth);
+            SkScalar bottom = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
+                    + 0.5f * strokeWidth);
+            canvas->drawRectCoords(left, top, right, bottom, *paint);
+        }
+    }
+}
+
     static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
             jfloat x, jfloat y, int flags, SkPaint* paint) {
         // Beware: this needs Glyph encoding (already done on the Paint constructor)
         canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
     }
 
+    static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
+            int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
+        SkPoint* posPtr = new SkPoint[count];
+        for (int indx = 0; indx < count; indx++) {
+            posPtr[indx].fX = SkFloatToScalar(x + posArray[indx * 2]);
+            posPtr[indx].fY = SkFloatToScalar(y + posArray[indx * 2 + 1]);
+        }
+        canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
+        delete[] posPtr;
+    }
+
     static void drawTextRun___CIIIIFFIPaint(
         JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index,
         int count, int contextIndex, int contextCount,
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 35f82a8..9b9b991 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -30,14 +30,6 @@
 namespace android {
 
 //--------------------------------------------------------------------------------------------------
-#define TYPEFACE_ARABIC "/system/fonts/DroidNaskh-Regular-SystemUI.ttf"
-#define TYPE_FACE_HEBREW_REGULAR "/system/fonts/DroidSansHebrew-Regular.ttf"
-#define TYPE_FACE_HEBREW_BOLD "/system/fonts/DroidSansHebrew-Bold.ttf"
-#define TYPEFACE_BENGALI "/system/fonts/Lohit-Bengali.ttf"
-#define TYPEFACE_DEVANAGARI_REGULAR "/system/fonts/DroidSansDevanagari-Regular.ttf"
-#define TYPEFACE_TAMIL_REGULAR "/system/fonts/DroidSansTamil-Regular.ttf"
-#define TYPEFACE_TAMIL_BOLD "/system/fonts/DroidSansTamil-Bold.ttf"
-#define TYPEFACE_THAI "/system/fonts/DroidSansThai.ttf"
 
 ANDROID_SINGLETON_STATIC_INSTANCE(TextLayoutEngine);
 
@@ -316,11 +308,12 @@
     // Give a hint for advances and glyphs vectors size
     mAdvances.setCapacity(contextCount);
     mGlyphs.setCapacity(contextCount);
+    mPos.setCapacity(contextCount * 2);
 }
 
 size_t TextLayoutValue::getSize() const {
     return sizeof(TextLayoutValue) + sizeof(jfloat) * mAdvances.capacity() +
-            sizeof(jchar) * mGlyphs.capacity();
+            sizeof(jchar) * mGlyphs.capacity() + sizeof(jfloat) * mPos.capacity();
 }
 
 void TextLayoutValue::setElapsedTime(uint32_t time) {
@@ -337,13 +330,9 @@
     mFontRec.klass = &harfbuzzSkiaClass;
     mFontRec.userData = 0;
 
-    // The values which harfbuzzSkiaClass returns are already scaled to
-    // pixel units, so we just set all these to one to disable further
-    // scaling.
-    mFontRec.x_ppem = 1;
-    mFontRec.y_ppem = 1;
-    mFontRec.x_scale = 1;
-    mFontRec.y_scale = 1;
+    // Note that the scaling values (x_ and y_ppem, x_ and y_scale) will be set
+    // below, when the paint transform and em unit of the actual shaping font
+    // are known.
 
     memset(&mShaperItem, 0, sizeof(mShaperItem));
 
@@ -353,26 +342,10 @@
 
 void TextLayoutShaper::init() {
     mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, SkTypeface::kNormal);
-    mArabicTypeface = NULL;
-    mHebrewRegularTypeface = NULL;
-    mHebrewBoldTypeface = NULL;
-    mBengaliTypeface = NULL;
-    mThaiTypeface = NULL;
-    mDevanagariRegularTypeface = NULL;
-    mTamilRegularTypeface = NULL;
-    mTamilBoldTypeface = NULL;
 }
 
 void TextLayoutShaper::unrefTypefaces() {
     SkSafeUnref(mDefaultTypeface);
-    SkSafeUnref(mArabicTypeface);
-    SkSafeUnref(mHebrewRegularTypeface);
-    SkSafeUnref(mHebrewBoldTypeface);
-    SkSafeUnref(mBengaliTypeface);
-    SkSafeUnref(mThaiTypeface);
-    SkSafeUnref(mDevanagariRegularTypeface);
-    SkSafeUnref(mTamilRegularTypeface);
-    SkSafeUnref(mTamilBoldTypeface);
 }
 
 TextLayoutShaper::~TextLayoutShaper() {
@@ -384,7 +357,7 @@
         size_t start, size_t count, size_t contextCount, int dirFlags) {
 
     computeValues(paint, chars, start, count, contextCount, dirFlags,
-            &value->mAdvances, &value->mTotalAdvance, &value->mGlyphs);
+            &value->mAdvances, &value->mTotalAdvance, &value->mGlyphs, &value->mPos);
 #if DEBUG_ADVANCES
     ALOGD("Advances - start = %d, count = %d, contextCount = %d, totalAdvance = %f", start, count,
             contextCount, value->mTotalAdvance);
@@ -394,9 +367,9 @@
 void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
         size_t start, size_t count, size_t contextCount, int dirFlags,
         Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-        Vector<jchar>* const outGlyphs) {
+        Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) {
+        *outTotalAdvance = 0;
         if (!count) {
-            *outTotalAdvance = 0;
             return;
         }
 
@@ -461,6 +434,7 @@
                                 ALOGW("Visual run is not valid");
                                 outGlyphs->clear();
                                 outAdvances->clear();
+                                outPos->clear();
                                 *outTotalAdvance = 0;
                                 isRTL = (paraDir == 1);
                                 useSingleRun = true;
@@ -483,15 +457,13 @@
 
                             lengthRun = endRun - startRun;
                             isRTL = (runDir == UBIDI_RTL);
-                            jfloat runTotalAdvance = 0;
 #if DEBUG_GLYPHS
                             ALOGD("Processing Bidi Run = %d -- run-start = %d, run-len = %d, isRTL = %d",
                                     i, startRun, lengthRun, isRTL);
 #endif
                             computeRunValues(paint, chars + startRun, lengthRun, isRTL,
-                                    outAdvances, &runTotalAdvance, outGlyphs);
+                                    outAdvances, outTotalAdvance, outGlyphs, outPos);
 
-                            *outTotalAdvance += runTotalAdvance;
                         }
                     }
                 } else {
@@ -514,7 +486,7 @@
                     "-- run-start = %d, run-len = %d, isRTL = %d", start, count, isRTL);
 #endif
             computeRunValues(paint, chars + start, count, isRTL,
-                    outAdvances, outTotalAdvance, outGlyphs);
+                    outAdvances, outTotalAdvance, outGlyphs, outPos);
         }
 
 #if DEBUG_GLYPHS
@@ -536,10 +508,9 @@
 void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars,
         size_t count, bool isRTL,
         Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-        Vector<jchar>* const outGlyphs) {
+        Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) {
     if (!count) {
         // We cannot shape an empty run.
-        *outTotalAdvance = 0;
         return;
     }
 
@@ -639,7 +610,8 @@
 
     // Define shaping paint properties
     mShapingPaint.setTextSize(paint->getTextSize());
-    mShapingPaint.setTextSkewX(paint->getTextSkewX());
+    float skewX = paint->getTextSkewX();
+    mShapingPaint.setTextSkewX(skewX);
     mShapingPaint.setTextScaleX(paint->getTextScaleX());
     mShapingPaint.setFlags(paint->getFlags());
     mShapingPaint.setHinting(paint->getHinting());
@@ -648,7 +620,7 @@
     // into the shaperItem
     ssize_t indexFontRun = isRTL ? mShaperItem.stringLength - 1 : 0;
     unsigned numCodePoints = 0;
-    jfloat totalAdvance = 0;
+    jfloat totalAdvance = *outTotalAdvance;
     while ((isRTL) ?
             hb_utf16_script_run_prev(&numCodePoints, &mShaperItem.item, mShaperItem.string,
                     mShaperItem.stringLength, &indexFontRun):
@@ -716,7 +688,6 @@
             currentAdvance = HBFixedToFloat(mShaperItem.advances[i]);
             totalFontRunAdvance += currentAdvance;
         }
-        totalAdvance += totalFontRunAdvance;
 
 #if DEBUG_ADVANCES
         ALOGD("Returned advances");
@@ -741,6 +712,30 @@
                 outGlyphs->add(glyph);
             }
         }
+
+        // Get glyph positions (and reverse them in place if RTL)
+        if (outPos) {
+            size_t countGlyphs = mShaperItem.num_glyphs;
+            jfloat x = totalAdvance;
+            for (size_t i = 0; i < countGlyphs; i++) {
+                size_t index = (!isRTL) ? i : countGlyphs - 1 - i;
+                float xo = HBFixedToFloat(mShaperItem.offsets[index].x);
+                float yo = HBFixedToFloat(mShaperItem.offsets[index].y);
+                // Apply skewX component of transform to position offsets. Note
+                // that scale has already been applied through x_ and y_scale
+                // set in the mFontRec.
+                outPos->add(x + xo + yo * skewX);
+                outPos->add(yo);
+#if DEBUG_GLYPHS
+                ALOGD("         -- hb adv[%d] = %f, log_cluster[%d] = %d",
+                        index, HBFixedToFloat(mShaperItem.advances[index]),
+                        index, mShaperItem.log_clusters[index]);
+#endif
+                x += HBFixedToFloat(mShaperItem.advances[index]);
+            }
+        }
+
+        totalAdvance += totalFontRunAdvance;
     }
 
     *outTotalAdvance = totalAdvance;
@@ -758,105 +753,32 @@
  * assumption is that its lifetime is managed elsewhere - in particular, the fallback typefaces
  * for the default font live in a global cache.
  */
-SkTypeface* TextLayoutShaper::typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface,
-        SkUnichar unichar, HB_Script script) {
-    // Set the correct Typeface depending on the script
-    switch (script) {
-    case HB_Script_Arabic:
-        typeface = getCachedTypeface(&mArabicTypeface, TYPEFACE_ARABIC);
-#if DEBUG_GLYPHS
-        ALOGD("Using Arabic Typeface");
-#endif
-        break;
-
-    case HB_Script_Hebrew:
-        if (typeface) {
-            switch (typeface->style()) {
-            case SkTypeface::kBold:
-            case SkTypeface::kBoldItalic:
-                typeface = getCachedTypeface(&mHebrewBoldTypeface, TYPE_FACE_HEBREW_BOLD);
-#if DEBUG_GLYPHS
-                ALOGD("Using Hebrew Bold/BoldItalic Typeface");
-#endif
-                break;
-
-            case SkTypeface::kNormal:
-            case SkTypeface::kItalic:
-            default:
-                typeface = getCachedTypeface(&mHebrewRegularTypeface, TYPE_FACE_HEBREW_REGULAR);
-#if DEBUG_GLYPHS
-                ALOGD("Using Hebrew Regular/Italic Typeface");
-#endif
-                break;
-            }
-        } else {
-            typeface = getCachedTypeface(&mHebrewRegularTypeface, TYPE_FACE_HEBREW_REGULAR);
-#if DEBUG_GLYPHS
-            ALOGD("Using Hebrew Regular Typeface");
-#endif
-        }
-        break;
-
-    case HB_Script_Bengali:
-        typeface = getCachedTypeface(&mBengaliTypeface, TYPEFACE_BENGALI);
-#if DEBUG_GLYPHS
-        ALOGD("Using Bengali Typeface");
-#endif
-        break;
-
-    case HB_Script_Thai:
-        typeface = getCachedTypeface(&mThaiTypeface, TYPEFACE_THAI);
-#if DEBUG_GLYPHS
-        ALOGD("Using Thai Typeface");
-#endif
-        break;
-
-    case HB_Script_Devanagari:
-       typeface = getCachedTypeface(&mDevanagariRegularTypeface, TYPEFACE_DEVANAGARI_REGULAR);
-#if DEBUG_GLYPHS
-       ALOGD("Using Devanagari Regular Typeface");
-#endif
-        break;
-
-    case HB_Script_Tamil:
-        if (typeface) {
-            switch (typeface->style()) {
-            case SkTypeface::kBold:
-            case SkTypeface::kBoldItalic:
-                typeface = getCachedTypeface(&mTamilBoldTypeface, TYPEFACE_TAMIL_BOLD);
-#if DEBUG_GLYPHS
-                ALOGD("Using Tamil Bold Typeface");
-#endif
-                break;
-
-            case SkTypeface::kNormal:
-            case SkTypeface::kItalic:
-            default:
-                typeface = getCachedTypeface(&mTamilRegularTypeface, TYPEFACE_TAMIL_REGULAR);
-#if DEBUG_GLYPHS
-                ALOGD("Using Tamil Regular Typeface");
-#endif
-                break;
-            }
-        } else {
-            typeface = getCachedTypeface(&mTamilRegularTypeface, TYPEFACE_TAMIL_REGULAR);
-#if DEBUG_GLYPHS
-            ALOGD("Using Tamil Regular Typeface");
-#endif
-        }
-        break;
-
-    default:
-#if DEBUG_GLYPHS
-        if (typeface) {
-            ALOGD("Using Paint Typeface");
-        }
-#endif
-        break;
+SkTypeface* TextLayoutShaper::typefaceForScript(const SkPaint* paint, SkTypeface* typeface,
+        HB_Script script) {
+    SkTypeface::Style currentStyle = SkTypeface::kNormal;
+    if (typeface) {
+        currentStyle = typeface->style();
     }
+    typeface = SkCreateTypefaceForScript(script, currentStyle);
+#if DEBUG_GLYPHS
+    ALOGD("Using Harfbuzz Script %d, Style %d", script, currentStyle);
+#endif
     return typeface;
 }
 
+bool TextLayoutShaper::isComplexScript(HB_Script script) {
+    switch (script) {
+    case HB_Script_Common:
+    case HB_Script_Greek:
+    case HB_Script_Cyrillic:
+    case HB_Script_Hangul:
+    case HB_Script_Inherited:
+        return false;
+    default:
+        return true;
+    }
+}
+
 size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) {
     // Reset kerning
     mShaperItem.kerning_applied = false;
@@ -872,63 +794,76 @@
     // If we are a "common" script we dont need to shift
     size_t baseGlyphCount = 0;
     SkUnichar firstUnichar = 0;
-    switch (mShaperItem.item.script) {
-    case HB_Script_Arabic:
-    case HB_Script_Hebrew:
-    case HB_Script_Bengali:
-    case HB_Script_Devanagari:
-    case HB_Script_Tamil:
-    case HB_Script_Thai:{
-        const uint16_t* text16 = (const uint16_t*)(mShaperItem.string + mShaperItem.item.pos);
+    if (isComplexScript(mShaperItem.item.script)) {
+        const uint16_t* text16 = (const uint16_t*) (mShaperItem.string + mShaperItem.item.pos);
         const uint16_t* text16End = text16 + mShaperItem.item.length;
         firstUnichar = SkUTF16_NextUnichar(&text16);
         while (firstUnichar == ' ' && text16 < text16End) {
             firstUnichar = SkUTF16_NextUnichar(&text16);
         }
         baseGlyphCount = paint->getBaseGlyphCount(firstUnichar);
-        break;
-    }
-    default:
-        break;
     }
 
-    // We test the baseGlyphCount to see if the typeface supports the requested script
     if (baseGlyphCount != 0) {
-        typeface = typefaceForUnichar(paint, typeface, firstUnichar, mShaperItem.item.script);
+        typeface = typefaceForScript(paint, typeface, mShaperItem.item.script);
+        if (!typeface) {
+            typeface = mDefaultTypeface;
+            SkSafeRef(typeface);
+#if DEBUG_GLYPHS
+            ALOGD("Using Default Typeface");
+#endif
+        }
+    } else {
+        if (!typeface) {
+            typeface = mDefaultTypeface;
+#if DEBUG_GLYPHS
+            ALOGD("Using Default Typeface");
+#endif
+        }
+        SkSafeRef(typeface);
     }
 
-    if (!typeface) {
-        typeface = mDefaultTypeface;
-#if DEBUG_GLYPHS
-        ALOGD("Using Default Typeface");
-#endif
-    }
     mShapingPaint.setTypeface(typeface);
     mShaperItem.face = getCachedHBFace(typeface);
 
+    int textSize = paint->getTextSize();
+    float scaleX = paint->getTextScaleX();
+    mFontRec.x_ppem = floor(scaleX * textSize + 0.5);
+    mFontRec.y_ppem = textSize;
+    uint32_t unitsPerEm = SkFontHost::GetUnitsPerEm(typeface->uniqueID());
+    // x_ and y_scale are the conversion factors from font design space
+    // (unitsPerEm) to 1/64th of device pixels in 16.16 format.
+    const int kDevicePixelFraction = 64;
+    const int kMultiplyFor16Dot16 = 1 << 16;
+    float emScale = kDevicePixelFraction * kMultiplyFor16Dot16 / (float)unitsPerEm;
+    mFontRec.x_scale = emScale * scaleX * textSize;
+    mFontRec.y_scale = emScale * textSize;
+
 #if DEBUG_GLYPHS
     ALOGD("Run typeface = %p, uniqueID = %d, hb_face = %p",
             typeface, typeface->uniqueID(), mShaperItem.face);
 #endif
+    SkSafeUnref(typeface);
 
     // Shape
     assert(mShaperItem.item.length > 0); // Harfbuzz will overwrite other memory if length is 0.
-    ensureShaperItemGlyphArrays(mShaperItem.item.length * 3 / 2);
-    mShaperItem.num_glyphs = mShaperItemGlyphArraySize;
-    while (!HB_ShapeItem(&mShaperItem)) {
+    size_t size = mShaperItem.item.length * 3 / 2;
+    while (!doShaping(size)) {
         // We overflowed our glyph arrays. Resize and retry.
         // HB_ShapeItem fills in shaperItem.num_glyphs with the needed size.
-        ensureShaperItemGlyphArrays(mShaperItem.num_glyphs * 2);
-        mShaperItem.num_glyphs = mShaperItemGlyphArraySize;
+        size = mShaperItem.num_glyphs * 2;
     }
     return baseGlyphCount;
 }
 
-void TextLayoutShaper::ensureShaperItemGlyphArrays(size_t size) {
+bool TextLayoutShaper::doShaping(size_t size) {
     if (size > mShaperItemGlyphArraySize) {
         deleteShaperItemGlyphArrays();
         createShaperItemGlyphArrays(size);
     }
+    mShaperItem.num_glyphs = mShaperItemGlyphArraySize;
+    memset(mShaperItem.offsets, 0, mShaperItem.num_glyphs * sizeof(HB_FixedPoint));
+    return HB_ShapeItem(&mShaperItem);
 }
 
 void TextLayoutShaper::createShaperItemGlyphArrays(size_t size) {
@@ -957,24 +892,6 @@
     delete[] mShaperItem.log_clusters;
 }
 
-SkTypeface* TextLayoutShaper::getCachedTypeface(SkTypeface** typeface, const char path[]) {
-    if (!*typeface) {
-        *typeface = SkTypeface::CreateFromFile(path);
-        // CreateFromFile(path) can return NULL if the path is non existing
-        if (!*typeface) {
-#if DEBUG_GLYPHS
-        ALOGD("Font path '%s' is not valid, will use default font", path);
-#endif
-            return mDefaultTypeface;
-        }
-        (*typeface)->ref();
-#if DEBUG_GLYPHS
-        ALOGD("Created SkTypeface from file '%s' with uniqueID = %d", path, (*typeface)->uniqueID());
-#endif
-    }
-    return *typeface;
-}
-
 HB_Face TextLayoutShaper::getCachedHBFace(SkTypeface* typeface) {
     SkFontID fontId = typeface->uniqueID();
     ssize_t index = mCachedHBFaces.indexOfKey(fontId);
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index cb15a2a..f007f9a 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -32,6 +32,7 @@
 #include <SkTemplates.h>
 #include <SkUtils.h>
 #include <SkAutoKern.h>
+#include "SkTypeface_android.h"
 
 #include <unicode/ubidi.h>
 #include <unicode/ushape.h>
@@ -56,7 +57,7 @@
 #define MB(s) s * 1024 * 1024
 
 // Define the default cache size in Mb
-#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
+#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.500f
 
 // Define the interval in number of cache hits between two statistics dump
 #define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
@@ -129,6 +130,8 @@
     inline jfloat getTotalAdvance() const { return mTotalAdvance; }
     inline const jchar* getGlyphs() const { return mGlyphs.array(); }
     inline size_t getGlyphsCount() const { return mGlyphs.size(); }
+    inline const jfloat* getPos() const { return mPos.array(); }
+    inline size_t getPosCount() const { return mPos.size(); }
 
     /**
      * Advances vector
@@ -146,6 +149,11 @@
     Vector<jchar> mGlyphs;
 
     /**
+     * Pos vector (2 * i is x pos, 2 * i + 1 is y pos, same as drawPosText)
+     */
+    Vector<jfloat> mPos;
+
+    /**
      * Get the size of the Cache entry
      */
     size_t getSize() const;
@@ -188,17 +196,9 @@
     SkPaint mShapingPaint;
 
     /**
-     * Skia typefaces cached for shaping
+     * Skia default typeface to be returned if we cannot resolve script
      */
     SkTypeface* mDefaultTypeface;
-    SkTypeface* mArabicTypeface;
-    SkTypeface* mHebrewRegularTypeface;
-    SkTypeface* mHebrewBoldTypeface;
-    SkTypeface* mBengaliTypeface;
-    SkTypeface* mThaiTypeface;
-    SkTypeface* mDevanagariRegularTypeface;
-    SkTypeface* mTamilRegularTypeface;
-    SkTypeface* mTamilBoldTypeface;
 
     /**
      * Cache of Harfbuzz faces
@@ -223,27 +223,28 @@
     void init();
     void unrefTypefaces();
 
-    SkTypeface* typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface,
-        SkUnichar unichar, HB_Script script);
+    SkTypeface* typefaceForScript(const SkPaint* paint, SkTypeface* typeface,
+        HB_Script script);
 
     size_t shapeFontRun(const SkPaint* paint, bool isRTL);
 
     void computeValues(const SkPaint* paint, const UChar* chars,
             size_t start, size_t count, size_t contextCount, int dirFlags,
             Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-            Vector<jchar>* const outGlyphs);
+            Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos);
 
     void computeRunValues(const SkPaint* paint, const UChar* chars,
             size_t count, bool isRTL,
             Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-            Vector<jchar>* const outGlyphs);
+            Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos);
 
-    SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]);
+    SkTypeface* getCachedTypeface(SkTypeface** typeface, HB_Script script, SkTypeface::Style style);
     HB_Face getCachedHBFace(SkTypeface* typeface);
 
-    void ensureShaperItemGlyphArrays(size_t size);
+    bool doShaping(size_t size);
     void createShaperItemGlyphArrays(size_t size);
     void deleteShaperItemGlyphArrays();
+    bool isComplexScript(HB_Script script);
 
 }; // TextLayoutShaper
 
diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
deleted file mode 100644
index 294c626..0000000
--- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BluetoothAudioGateway.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_bluetooth_c.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#define USE_ACCEPT_DIRECTLY (0)
-#define USE_SELECT (0) /* 1 for select(), 0 for poll(); used only when
-                          USE_ACCEPT_DIRECTLY == 0 */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/uio.h>
-#include <ctype.h>
-
-#if USE_SELECT
-#include <sys/select.h>
-#else
-#include <sys/poll.h>
-#endif
-
-#ifdef HAVE_BLUETOOTH
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sco.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static jfieldID field_mNativeData;
-    /* in */
-static jfieldID field_mHandsfreeAgRfcommChannel;
-static jfieldID field_mHeadsetAgRfcommChannel;
-    /* out */
-static jfieldID field_mTimeoutRemainingMs; /* out */
-
-static jfieldID field_mConnectingHeadsetAddress;
-static jfieldID field_mConnectingHeadsetRfcommChannel; /* -1 when not connected */
-static jfieldID field_mConnectingHeadsetSocketFd;
-
-static jfieldID field_mConnectingHandsfreeAddress;
-static jfieldID field_mConnectingHandsfreeRfcommChannel; /* -1 when not connected */
-static jfieldID field_mConnectingHandsfreeSocketFd;
-
-
-typedef struct {
-    int hcidev;
-    int hf_ag_rfcomm_channel;
-    int hs_ag_rfcomm_channel;
-    int hf_ag_rfcomm_sock;
-    int hs_ag_rfcomm_sock;
-} native_data_t;
-
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    return (native_data_t *)(env->GetIntField(object,
-                                                 field_mNativeData));
-}
-
-static int setup_listening_socket(int dev, int channel);
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-
-    /* in */
-    field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mHandsfreeAgRfcommChannel =
-        get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I");
-    field_mHeadsetAgRfcommChannel =
-        get_field(env, clazz, "mHeadsetAgRfcommChannel", "I");
-
-    /* out */
-    field_mConnectingHeadsetAddress =
-        get_field(env, clazz,
-                  "mConnectingHeadsetAddress", "Ljava/lang/String;");
-    field_mConnectingHeadsetRfcommChannel =
-        get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I");
-    field_mConnectingHeadsetSocketFd =
-        get_field(env, clazz, "mConnectingHeadsetSocketFd", "I");
-
-    field_mConnectingHandsfreeAddress =
-        get_field(env, clazz,
-                  "mConnectingHandsfreeAddress", "Ljava/lang/String;");
-    field_mConnectingHandsfreeRfcommChannel =
-        get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I");
-    field_mConnectingHandsfreeSocketFd =
-        get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I");
-
-    field_mTimeoutRemainingMs =
-        get_field(env, clazz, "mTimeoutRemainingMs", "I");
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return;
-    }
-
-    nat->hcidev = BLUETOOTH_ADAPTER_HCI_NUM;
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-    nat->hf_ag_rfcomm_channel =
-        env->GetIntField(object, field_mHandsfreeAgRfcommChannel);
-    nat->hs_ag_rfcomm_channel =
-        env->GetIntField(object, field_mHeadsetAgRfcommChannel);
-    ALOGV("HF RFCOMM channel = %d.", nat->hf_ag_rfcomm_channel);
-    ALOGV("HS RFCOMM channel = %d.", nat->hs_ag_rfcomm_channel);
-
-    /* Set the default values of these to -1. */
-    env->SetIntField(object, field_mConnectingHeadsetRfcommChannel, -1);
-    env->SetIntField(object, field_mConnectingHandsfreeRfcommChannel, -1);
-
-    nat->hf_ag_rfcomm_sock = -1;
-    nat->hs_ag_rfcomm_sock = -1;
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        free(nat);
-    }
-#endif
-}
-
-#ifdef HAVE_BLUETOOTH
-
-#if USE_ACCEPT_DIRECTLY==0
-static int set_nb(int sk, bool nb) {
-    int flags = fcntl(sk, F_GETFL);
-    if (flags < 0) {
-        ALOGE("Can't get socket flags with fcntl(): %s (%d)",
-             strerror(errno), errno);
-        close(sk);
-        return -1;
-    }
-    flags &= ~O_NONBLOCK;
-    if (nb) flags |= O_NONBLOCK;
-    int status = fcntl(sk, F_SETFL, flags);
-    if (status < 0) {
-        ALOGE("Can't set socket to nonblocking mode with fcntl(): %s (%d)",
-             strerror(errno), errno);
-        close(sk);
-        return -1;
-    }
-    return 0;
-}
-#endif /*USE_ACCEPT_DIRECTLY==0*/
-
-static int do_accept(JNIEnv* env, jobject object, int ag_fd,
-                     jfieldID out_fd,
-                     jfieldID out_address,
-                     jfieldID out_channel) {
-
-#if USE_ACCEPT_DIRECTLY==0
-    if (set_nb(ag_fd, true) < 0)
-        return -1;
-#endif
-
-    struct sockaddr_rc raddr;
-    int alen = sizeof(raddr);
-    int nsk = TEMP_FAILURE_RETRY(accept(ag_fd, (struct sockaddr *) &raddr, &alen));
-    if (nsk < 0) {
-        ALOGE("Error on accept from socket fd %d: %s (%d).",
-             ag_fd,
-             strerror(errno),
-             errno);
-#if USE_ACCEPT_DIRECTLY==0
-        set_nb(ag_fd, false);
-#endif
-        return -1;
-    }
-
-    env->SetIntField(object, out_fd, nsk);
-    env->SetIntField(object, out_channel, raddr.rc_channel);
-
-    char addr[BTADDR_SIZE];
-    get_bdaddr_as_string(&raddr.rc_bdaddr, addr);
-    env->SetObjectField(object, out_address, env->NewStringUTF(addr));
-
-    ALOGI("Successful accept() on AG socket %d: new socket %d, address %s, RFCOMM channel %d",
-         ag_fd,
-         nsk,
-         addr,
-         raddr.rc_channel);
-#if USE_ACCEPT_DIRECTLY==0
-    set_nb(ag_fd, false);
-#endif
-    return 0;
-}
-
-#if USE_SELECT
-static inline int on_accept_set_fields(JNIEnv* env, jobject object,
-                                       fd_set *rset, int ag_fd,
-                                       jfieldID out_fd,
-                                       jfieldID out_address,
-                                       jfieldID out_channel) {
-
-    env->SetIntField(object, out_channel, -1);
-
-    if (ag_fd >= 0 && FD_ISSET(ag_fd, &rset)) {
-        return do_accept(env, object, ag_fd,
-                         out_fd, out_address, out_channel);
-    }
-    else {
-        ALOGI("fd = %d, FD_ISSET() = %d",
-             ag_fd,
-             FD_ISSET(ag_fd, &rset));
-        if (ag_fd >= 0 && !FD_ISSET(ag_fd, &rset)) {
-            ALOGE("WTF???");
-            return -1;
-        }
-    }
-
-    return 0;
-}
-#endif
-#endif /* HAVE_BLUETOOTH */
-
-static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object,
-                                              jint timeout_ms) {
-//    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-
-    env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms);
-
-    int n = 0;
-    native_data_t *nat = get_native_data(env, object);
-#if USE_ACCEPT_DIRECTLY
-    if (nat->hf_ag_rfcomm_channel > 0) {
-        ALOGI("Setting HF AG server socket to RFCOMM port %d!",
-             nat->hf_ag_rfcomm_channel);
-        struct timeval tv;
-        int len = sizeof(tv);
-        if (getsockopt(nat->hf_ag_rfcomm_channel,
-                       SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) {
-            ALOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)",
-                 nat->hf_ag_rfcomm_channel,
-                 strerror(errno),
-                 errno);
-            return JNI_FALSE;
-        }
-        ALOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!",
-             (int)tv.tv_sec, (int)tv.tv_usec);
-        if (timeout_ms >= 0) {
-            tv.tv_sec = timeout_ms / 1000;
-            tv.tv_usec = 1000 * (timeout_ms % 1000);
-            if (setsockopt(nat->hf_ag_rfcomm_channel,
-                           SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
-                ALOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)",
-                     nat->hf_ag_rfcomm_channel,
-                     strerror(errno),
-                     errno);
-                return JNI_FALSE;
-            }
-            ALOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!",
-                 (int)tv.tv_sec, (int)tv.tv_usec);
-        }
-
-        if (!do_accept(env, object, nat->hf_ag_rfcomm_sock,
-                       field_mConnectingHandsfreeSocketFd,
-                       field_mConnectingHandsfreeAddress,
-                       field_mConnectingHandsfreeRfcommChannel))
-        {
-            env->SetIntField(object, field_mTimeoutRemainingMs, 0);
-            return JNI_TRUE;
-        }
-        return JNI_FALSE;
-    }
-#else
-#if USE_SELECT
-    fd_set rset;
-    FD_ZERO(&rset);
-    int cnt = 0;
-    if (nat->hf_ag_rfcomm_channel > 0) {
-        ALOGI("Setting HF AG server socket to RFCOMM port %d!",
-             nat->hf_ag_rfcomm_channel);
-        cnt++;
-        FD_SET(nat->hf_ag_rfcomm_sock, &rset);
-    }
-    if (nat->hs_ag_rfcomm_channel > 0) {
-        ALOGI("Setting HS AG server socket to RFCOMM port %d!",
-             nat->hs_ag_rfcomm_channel);
-        cnt++;
-        FD_SET(nat->hs_ag_rfcomm_sock, &rset);
-    }
-    if (cnt == 0) {
-        ALOGE("Neither HF nor HS listening sockets are open!");
-        return JNI_FALSE;
-    }
-
-    struct timeval to;
-    if (timeout_ms >= 0) {
-        to.tv_sec = timeout_ms / 1000;
-        to.tv_usec = 1000 * (timeout_ms % 1000);
-    }
-    n = TEMP_FAILURE_RETRY(select(
-                   MAX(nat->hf_ag_rfcomm_sock, nat->hs_ag_rfcomm_sock) + 1,
-                   &rset,
-                   NULL,
-                   NULL,
-                   (timeout_ms < 0 ? NULL : &to)));
-    if (timeout_ms > 0) {
-        jint remaining = to.tv_sec*1000 + to.tv_usec/1000;
-        ALOGI("Remaining time %ldms", (long)remaining);
-        env->SetIntField(object, field_mTimeoutRemainingMs,
-                         remaining);
-    }
-
-    ALOGI("listening select() returned %d", n);
-
-    if (n <= 0) {
-        if (n < 0)  {
-            ALOGE("listening select() on RFCOMM sockets: %s (%d)",
-                 strerror(errno),
-                 errno);
-        }
-        return JNI_FALSE;
-    }
-
-    n = on_accept_set_fields(env, object,
-                             &rset, nat->hf_ag_rfcomm_sock,
-                             field_mConnectingHandsfreeSocketFd,
-                             field_mConnectingHandsfreeAddress,
-                             field_mConnectingHandsfreeRfcommChannel);
-
-    n += on_accept_set_fields(env, object,
-                              &rset, nat->hs_ag_rfcomm_sock,
-                              field_mConnectingHeadsetSocketFd,
-                              field_mConnectingHeadsetAddress,
-                              field_mConnectingHeadsetRfcommChannel);
-
-    return !n ? JNI_TRUE : JNI_FALSE;
-#else
-    struct pollfd fds[2];
-    int cnt = 0;
-    if (nat->hf_ag_rfcomm_channel > 0) {
-//        ALOGI("Setting HF AG server socket %d to RFCOMM port %d!",
-//             nat->hf_ag_rfcomm_sock,
-//             nat->hf_ag_rfcomm_channel);
-        fds[cnt].fd = nat->hf_ag_rfcomm_sock;
-        fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR;
-        cnt++;
-    }
-    if (nat->hs_ag_rfcomm_channel > 0) {
-//        ALOGI("Setting HS AG server socket %d to RFCOMM port %d!",
-//             nat->hs_ag_rfcomm_sock,
-//             nat->hs_ag_rfcomm_channel);
-        fds[cnt].fd = nat->hs_ag_rfcomm_sock;
-        fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR;
-        cnt++;
-    }
-    if (cnt == 0) {
-        ALOGE("Neither HF nor HS listening sockets are open!");
-        return JNI_FALSE;
-    }
-    n = TEMP_FAILURE_RETRY(poll(fds, cnt, timeout_ms));
-    if (n <= 0) {
-        if (n < 0)  {
-            ALOGE("listening poll() on RFCOMM sockets: %s (%d)",
-                 strerror(errno),
-                 errno);
-        }
-        else {
-            env->SetIntField(object, field_mTimeoutRemainingMs, 0);
-//            ALOGI("listening poll() on RFCOMM socket timed out");
-        }
-        return JNI_FALSE;
-    }
-
-    //ALOGI("listening poll() on RFCOMM socket returned %d", n);
-    int err = 0;
-    for (cnt = 0; cnt < (int)(sizeof(fds)/sizeof(fds[0])); cnt++) {
-        //ALOGI("Poll on fd %d revent = %d.", fds[cnt].fd, fds[cnt].revents);
-        if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) {
-            if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) {
-                ALOGI("Accepting HF connection.\n");
-                err += do_accept(env, object, fds[cnt].fd,
-                               field_mConnectingHandsfreeSocketFd,
-                               field_mConnectingHandsfreeAddress,
-                               field_mConnectingHandsfreeRfcommChannel);
-                n--;
-            }
-        }
-        else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) {
-            if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) {
-                ALOGI("Accepting HS connection.\n");
-                err += do_accept(env, object, fds[cnt].fd,
-                               field_mConnectingHeadsetSocketFd,
-                               field_mConnectingHeadsetAddress,
-                               field_mConnectingHeadsetRfcommChannel);
-                n--;
-            }
-        }
-    } /* for */
-
-    if (n != 0) {
-        ALOGI("Bogus poll(): %d fake pollfd entrie(s)!", n);
-        return JNI_FALSE;
-    }
-
-    return !err ? JNI_TRUE : JNI_FALSE;
-#endif /* USE_SELECT */
-#endif /* USE_ACCEPT_DIRECTLY */
-#else
-    return JNI_FALSE;
-#endif /* HAVE_BLUETOOTH */
-}
-
-static jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    nat->hf_ag_rfcomm_sock =
-        setup_listening_socket(nat->hcidev, nat->hf_ag_rfcomm_channel);
-    if (nat->hf_ag_rfcomm_sock < 0)
-        return JNI_FALSE;
-
-    nat->hs_ag_rfcomm_sock =
-        setup_listening_socket(nat->hcidev, nat->hs_ag_rfcomm_channel);
-    if (nat->hs_ag_rfcomm_sock < 0) {
-        close(nat->hf_ag_rfcomm_sock);
-        nat->hf_ag_rfcomm_sock = -1;
-        return JNI_FALSE;
-    }
-
-    return JNI_TRUE;
-#else
-    return JNI_FALSE;
-#endif /* HAVE_BLUETOOTH */
-}
-
-#ifdef HAVE_BLUETOOTH
-static int setup_listening_socket(int dev, int channel) {
-    struct sockaddr_rc laddr;
-    int sk, lm;
-
-    sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-    if (sk < 0) {
-        ALOGE("Can't create RFCOMM socket");
-        return -1;
-    }
-
-    if (debug_no_encrypt()) {
-        lm = RFCOMM_LM_AUTH;
-    } else {
-        lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
-    }
-
-    if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
-        ALOGE("Can't set RFCOMM link mode");
-        close(sk);
-        return -1;
-    }
-
-    laddr.rc_family = AF_BLUETOOTH;
-    bdaddr_t any = android_bluetooth_bdaddr_any();
-    memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t));
-    laddr.rc_channel = channel;
-
-    if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
-        ALOGE("Can't bind RFCOMM socket");
-        close(sk);
-        return -1;
-    }
-
-    listen(sk, 10);
-    return sk;
-}
-#endif /* HAVE_BLUETOOTH */
-
-/*
-    private native void tearDownListeningSocketsNative();
-*/
-static void tearDownListeningSocketsNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    if (nat->hf_ag_rfcomm_sock > 0) {
-        if (close(nat->hf_ag_rfcomm_sock) < 0) {
-            ALOGE("Could not close HF server socket: %s (%d)\n",
-                 strerror(errno), errno);
-        }
-        nat->hf_ag_rfcomm_sock = -1;
-    }
-    if (nat->hs_ag_rfcomm_sock > 0) {
-        if (close(nat->hs_ag_rfcomm_sock) < 0) {
-            ALOGE("Could not close HS server socket: %s (%d)\n",
-                 strerror(errno), errno);
-        }
-        nat->hs_ag_rfcomm_sock = -1;
-    }
-#endif /* HAVE_BLUETOOTH */
-}
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-
-    {"classInitNative", "()V", (void*)classInitNative},
-    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-
-    {"setUpListeningSocketsNative", "()Z", (void *)setUpListeningSocketsNative},
-    {"tearDownListeningSocketsNative", "()V", (void *)tearDownListeningSocketsNative},
-    {"waitForHandsfreeConnectNative", "(I)Z", (void *)waitForHandsfreeConnectNative},
-};
-
-int register_android_bluetooth_BluetoothAudioGateway(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-            "android/bluetooth/BluetoothAudioGateway", sMethods,
-            NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
deleted file mode 100644
index d9ff36a..0000000
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BluetoothSocket.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_bluetooth_c.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "utils/Log.h"
-#include "cutils/abort_socket.h"
-
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/sco.h>
-#endif
-
-#define TYPE_AS_STR(t) \
-    ((t) == TYPE_RFCOMM ? "RFCOMM" : ((t) == TYPE_SCO ? "SCO" : "L2CAP"))
-
-namespace android {
-
-static jfieldID  field_mAuth;     /* read-only */
-static jfieldID  field_mEncrypt;  /* read-only */
-static jfieldID  field_mType;     /* read-only */
-static jfieldID  field_mAddress;  /* read-only */
-static jfieldID  field_mPort;     /* read-only */
-static jfieldID  field_mSocketData;
-static jmethodID method_BluetoothSocket_ctor;
-static jclass    class_BluetoothSocket;
-
-/* Keep TYPE_RFCOMM etc in sync with BluetoothSocket.java */
-static const int TYPE_RFCOMM = 1;
-static const int TYPE_SCO = 2;
-static const int TYPE_L2CAP = 3;  // TODO: Test l2cap code paths
-
-static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
-
-static void abortNative(JNIEnv *env, jobject obj);
-static void destroyNative(JNIEnv *env, jobject obj);
-
-static struct asocket *get_socketData(JNIEnv *env, jobject obj) {
-    struct asocket *s =
-            (struct asocket *) env->GetIntField(obj, field_mSocketData);
-    if (!s)
-        jniThrowException(env, "java/io/IOException", "null socketData");
-    return s;
-}
-
-static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    struct asocket *s = asocket_init(fd);
-
-    if (!s) {
-        ALOGV("asocket_init() failed, throwing");
-        jniThrowIOException(env, errno);
-        return;
-    }
-
-    env->SetIntField(obj, field_mSocketData, (jint)s);
-
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void initSocketNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int fd;
-    int lm = 0;
-    int sndbuf;
-    jboolean auth;
-    jboolean encrypt;
-    jint type;
-
-    type = env->GetIntField(obj, field_mType);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-        break;
-    case TYPE_SCO:
-        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
-        break;
-    case TYPE_L2CAP:
-        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
-        break;
-    default:
-        jniThrowIOException(env, ENOSYS);
-        return;
-    }
-
-    if (fd < 0) {
-        ALOGV("socket() failed, throwing");
-        jniThrowIOException(env, errno);
-        return;
-    }
-
-    auth = env->GetBooleanField(obj, field_mAuth);
-    encrypt = env->GetBooleanField(obj, field_mEncrypt);
-
-    /* kernel does not yet support LM for SCO */
-    switch (type) {
-    case TYPE_RFCOMM:
-        lm |= auth ? RFCOMM_LM_AUTH : 0;
-        lm |= encrypt ? RFCOMM_LM_ENCRYPT : 0;
-        lm |= (auth && encrypt) ? RFCOMM_LM_SECURE : 0;
-        break;
-    case TYPE_L2CAP:
-        lm |= auth ? L2CAP_LM_AUTH : 0;
-        lm |= encrypt ? L2CAP_LM_ENCRYPT : 0;
-        lm |= (auth && encrypt) ? L2CAP_LM_SECURE : 0;
-        break;
-    }
-
-    if (lm) {
-        if (setsockopt(fd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
-            ALOGV("setsockopt(RFCOMM_LM) failed, throwing");
-            jniThrowIOException(env, errno);
-            return;
-        }
-    }
-
-    if (type == TYPE_RFCOMM) {
-        sndbuf = RFCOMM_SO_SNDBUF;
-        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
-            ALOGV("setsockopt(SO_SNDBUF) failed, throwing");
-            jniThrowIOException(env, errno);
-            return;
-        }
-    }
-
-    ALOGV("...fd %d created (%s, lm = %x)", fd, TYPE_AS_STR(type), lm);
-
-    initSocketFromFdNative(env, obj, fd);
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void connectNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int ret;
-    jint type;
-    const char *c_address;
-    jstring address;
-    bdaddr_t bdaddress;
-    socklen_t addr_sz;
-    struct sockaddr *addr;
-    struct asocket *s = get_socketData(env, obj);
-    int retry = 0;
-
-    if (!s)
-        return;
-
-    type = env->GetIntField(obj, field_mType);
-
-    /* parse address into bdaddress */
-    address = (jstring) env->GetObjectField(obj, field_mAddress);
-    c_address = env->GetStringUTFChars(address, NULL);
-    if (get_bdaddr(c_address, &bdaddress)) {
-        env->ReleaseStringUTFChars(address, c_address);
-        jniThrowIOException(env, EINVAL);
-        return;
-    }
-    env->ReleaseStringUTFChars(address, c_address);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        struct sockaddr_rc addr_rc;
-        addr = (struct sockaddr *)&addr_rc;
-        addr_sz = sizeof(addr_rc);
-
-        memset(addr, 0, addr_sz);
-        addr_rc.rc_family = AF_BLUETOOTH;
-        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_rc.rc_bdaddr, &bdaddress, sizeof(bdaddr_t));
-
-        break;
-    case TYPE_SCO:
-        struct sockaddr_sco addr_sco;
-        addr = (struct sockaddr *)&addr_sco;
-        addr_sz = sizeof(addr_sco);
-
-        memset(addr, 0, addr_sz);
-        addr_sco.sco_family = AF_BLUETOOTH;
-        memcpy(&addr_sco.sco_bdaddr, &bdaddress, sizeof(bdaddr_t));
-
-        break;
-    case TYPE_L2CAP:
-        struct sockaddr_l2 addr_l2;
-        addr = (struct sockaddr *)&addr_l2;
-        addr_sz = sizeof(addr_l2);
-
-        memset(addr, 0, addr_sz);
-        addr_l2.l2_family = AF_BLUETOOTH;
-        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_l2.l2_bdaddr, &bdaddress, sizeof(bdaddr_t));
-
-        break;
-    default:
-        jniThrowIOException(env, ENOSYS);
-        return;
-    }
-
-connect:
-    ret = asocket_connect(s, addr, addr_sz, -1);
-    ALOGV("...connect(%d, %s) = %d (errno %d)",
-            s->fd, TYPE_AS_STR(type), ret, errno);
-
-    if (ret && errno == EALREADY && retry < 2) {
-        /* workaround for bug 5082381 (EALREADY on ACL collision):
-         * retry the connect. Unfortunately we have to create a new fd.
-         * It's not ideal to switch the fd underneath the object, but
-         * is currently safe */
-        ALOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround");
-        usleep(100000);
-        retry++;
-        abortNative(env, obj);
-        destroyNative(env, obj);
-        initSocketNative(env, obj);
-        if (env->ExceptionOccurred()) {
-            return;
-        }
-        goto connect;
-    }
-    if (!ret && retry > 0)
-        ALOGD("...workaround ok");
-
-    if (ret)
-        jniThrowIOException(env, errno);
-
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-/* Returns errno instead of throwing, so java can check errno */
-static int bindListenNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    jint type;
-    socklen_t addr_sz;
-    struct sockaddr *addr;
-    bdaddr_t bdaddr = android_bluetooth_bdaddr_any();
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return EINVAL;
-
-    type = env->GetIntField(obj, field_mType);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        struct sockaddr_rc addr_rc;
-        addr = (struct sockaddr *)&addr_rc;
-        addr_sz = sizeof(addr_rc);
-
-        memset(addr, 0, addr_sz);
-        addr_rc.rc_family = AF_BLUETOOTH;
-        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_rc.rc_bdaddr, &bdaddr, sizeof(bdaddr_t));
-        break;
-    case TYPE_SCO:
-        struct sockaddr_sco addr_sco;
-        addr = (struct sockaddr *)&addr_sco;
-        addr_sz = sizeof(addr_sco);
-
-        memset(addr, 0, addr_sz);
-        addr_sco.sco_family = AF_BLUETOOTH;
-        memcpy(&addr_sco.sco_bdaddr, &bdaddr, sizeof(bdaddr_t));
-        break;
-    case TYPE_L2CAP:
-        struct sockaddr_l2 addr_l2;
-        addr = (struct sockaddr *)&addr_l2;
-        addr_sz = sizeof(addr_l2);
-
-        memset(addr, 0, addr_sz);
-        addr_l2.l2_family = AF_BLUETOOTH;
-        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_l2.l2_bdaddr, &bdaddr, sizeof(bdaddr_t));
-        break;
-    default:
-        return ENOSYS;
-    }
-
-    if (bind(s->fd, addr, addr_sz)) {
-        ALOGV("...bind(%d) gave errno %d", s->fd, errno);
-        return errno;
-    }
-
-    if (listen(s->fd, 1)) {
-        ALOGV("...listen(%d) gave errno %d", s->fd, errno);
-        return errno;
-    }
-
-    ALOGV("...bindListenNative(%d) success", s->fd);
-
-    return 0;
-
-#endif
-    return ENOSYS;
-}
-
-static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int fd;
-    jint type;
-    struct sockaddr *addr;
-    socklen_t addr_sz;
-    jstring addr_jstr;
-    char addr_cstr[BTADDR_SIZE];
-    bdaddr_t *bdaddr;
-    jboolean auth;
-    jboolean encrypt;
-
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return NULL;
-
-    type = env->GetIntField(obj, field_mType);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        struct sockaddr_rc addr_rc;
-        addr = (struct sockaddr *)&addr_rc;
-        addr_sz = sizeof(addr_rc);
-        bdaddr = &addr_rc.rc_bdaddr;
-        memset(addr, 0, addr_sz);
-        break;
-    case TYPE_SCO:
-        struct sockaddr_sco addr_sco;
-        addr = (struct sockaddr *)&addr_sco;
-        addr_sz = sizeof(addr_sco);
-        bdaddr = &addr_sco.sco_bdaddr;
-        memset(addr, 0, addr_sz);
-        break;
-    case TYPE_L2CAP:
-        struct sockaddr_l2 addr_l2;
-        addr = (struct sockaddr *)&addr_l2;
-        addr_sz = sizeof(addr_l2);
-        bdaddr = &addr_l2.l2_bdaddr;
-        memset(addr, 0, addr_sz);
-        break;
-    default:
-        jniThrowIOException(env, ENOSYS);
-        return NULL;
-    }
-
-    fd = asocket_accept(s, addr, &addr_sz, timeout);
-
-    ALOGV("...accept(%d, %s) = %d (errno %d)",
-            s->fd, TYPE_AS_STR(type), fd, errno);
-
-    if (fd < 0) {
-        jniThrowIOException(env, errno);
-        return NULL;
-    }
-
-    /* Connected - return new BluetoothSocket */
-    auth = env->GetBooleanField(obj, field_mAuth);
-    encrypt = env->GetBooleanField(obj, field_mEncrypt);
-
-    get_bdaddr_as_string(bdaddr, addr_cstr);
-
-    addr_jstr = env->NewStringUTF(addr_cstr);
-    return env->NewObject(class_BluetoothSocket, method_BluetoothSocket_ctor,
-            type, fd, auth, encrypt, addr_jstr, -1);
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return NULL;
-}
-
-static jint availableNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int available;
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return -1;
-
-    if (ioctl(s->fd, FIONREAD, &available) < 0) {
-        jniThrowIOException(env, errno);
-        return -1;
-    }
-
-    return available;
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return -1;
-}
-
-static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
-        jint length) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int ret;
-    jbyte *b;
-    int sz;
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return -1;
-    if (jb == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-    sz = env->GetArrayLength(jb);
-    if (offset < 0 || length < 0 || offset + length > sz) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    b = env->GetByteArrayElements(jb, NULL);
-    if (b == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    ret = asocket_read(s, &b[offset], length, -1);
-    if (ret < 0) {
-        jniThrowIOException(env, errno);
-        env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
-        return -1;
-    }
-
-    env->ReleaseByteArrayElements(jb, b, 0);
-    return (jint)ret;
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return -1;
-}
-
-static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
-        jint length) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int ret, total;
-    jbyte *b;
-    int sz;
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return -1;
-    if (jb == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-    sz = env->GetArrayLength(jb);
-    if (offset < 0 || length < 0 || offset + length > sz) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    b = env->GetByteArrayElements(jb, NULL);
-    if (b == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    total = 0;
-    while (length > 0) {
-        ret = asocket_write(s, &b[offset], length, -1);
-        if (ret < 0) {
-            jniThrowIOException(env, errno);
-            env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
-            return -1;
-        }
-        offset += ret;
-        total += ret;
-        length -= ret;
-    }
-
-    env->ReleaseByteArrayElements(jb, b, JNI_ABORT);  // no need to commit
-    return (jint)total;
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return -1;
-}
-
-static void abortNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return;
-
-    asocket_abort(s);
-
-    ALOGV("...asocket_abort(%d) complete", s->fd);
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void destroyNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    struct asocket *s = get_socketData(env, obj);
-    int fd = s->fd;
-
-    if (!s)
-        return;
-
-    asocket_destroy(s);
-
-    ALOGV("...asocket_destroy(%d) complete", fd);
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void throwErrnoNative(JNIEnv *env, jobject obj, jint err) {
-    jniThrowIOException(env, err);
-}
-
-static JNINativeMethod sMethods[] = {
-    {"initSocketNative", "()V",  (void*) initSocketNative},
-    {"initSocketFromFdNative", "(I)V",  (void*) initSocketFromFdNative},
-    {"connectNative", "()V", (void *) connectNative},
-    {"bindListenNative", "()I", (void *) bindListenNative},
-    {"acceptNative", "(I)Landroid/bluetooth/BluetoothSocket;", (void *) acceptNative},
-    {"availableNative", "()I",    (void *) availableNative},
-    {"readNative", "([BII)I",    (void *) readNative},
-    {"writeNative", "([BII)I",    (void *) writeNative},
-    {"abortNative", "()V",    (void *) abortNative},
-    {"destroyNative", "()V",    (void *) destroyNative},
-    {"throwErrnoNative", "(I)V",    (void *) throwErrnoNative},
-};
-
-int register_android_bluetooth_BluetoothSocket(JNIEnv *env) {
-    jclass clazz = env->FindClass("android/bluetooth/BluetoothSocket");
-    if (clazz == NULL)
-        return -1;
-    class_BluetoothSocket = (jclass) env->NewGlobalRef(clazz);
-    field_mType = env->GetFieldID(clazz, "mType", "I");
-    field_mAddress = env->GetFieldID(clazz, "mAddress", "Ljava/lang/String;");
-    field_mPort = env->GetFieldID(clazz, "mPort", "I");
-    field_mAuth = env->GetFieldID(clazz, "mAuth", "Z");
-    field_mEncrypt = env->GetFieldID(clazz, "mEncrypt", "Z");
-    field_mSocketData = env->GetFieldID(clazz, "mSocketData", "I");
-    method_BluetoothSocket_ctor = env->GetMethodID(clazz, "<init>", "(IIZZLjava/lang/String;I)V");
-    return AndroidRuntime::registerNativeMethods(env,
-        "android/bluetooth/BluetoothSocket", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
-
diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp
deleted file mode 100644
index 34447ef..0000000
--- a/core/jni/android_bluetooth_HeadsetBase.cpp
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BT HSHFP"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/poll.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sco.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static jfieldID field_mNativeData;
-static jfieldID field_mAddress;
-static jfieldID field_mRfcommChannel;
-static jfieldID field_mTimeoutRemainingMs;
-
-typedef struct {
-    jstring address;
-    const char *c_address;
-    int rfcomm_channel;
-    int last_read_err;
-    int rfcomm_sock;
-    int rfcomm_connected; // -1 in progress, 0 not connected, 1 connected
-    int rfcomm_sock_flags;
-} native_data_t;
-
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    return (native_data_t *)(env->GetIntField(object, field_mNativeData));
-}
-
-static const char CRLF[] = "\xd\xa";
-static const int CRLF_LEN = 2;
-
-static inline int write_error_check(int fd, const char* line, int len) {
-    int ret;
-    errno = 0;
-    ret = write(fd, line, len);
-    if (ret < 0) {
-        ALOGE("%s: write() failed: %s (%d)", __FUNCTION__, strerror(errno),
-             errno);
-        return -1;
-    }
-    if (ret != len) {
-        ALOGE("%s: write() only wrote %d of %d bytes", __FUNCTION__, ret, len);
-        return -1;
-    }
-    return 0;
-}
-
-static int send_line(int fd, const char* line) {
-    int nw;
-    int len = strlen(line);
-    int llen = len + CRLF_LEN * 2 + 1;
-    char *buffer = (char *)calloc(llen, sizeof(char));
-
-    snprintf(buffer, llen, "%s%s%s", CRLF, line, CRLF);
-
-    if (write_error_check(fd, buffer, llen - 1)) {
-        free(buffer);
-        return -1;
-    }
-    free(buffer);
-    return 0;
-}
-
-static void mask_eighth_bit(char *line)
-{
-   for (;;line++) {
-     if (0 == *line) return;
-     *line &= 0x7F;
-   }
-}
-
-static const char* get_line(int fd, char *buf, int len, int timeout_ms,
-                            int *err) {
-    char *bufit=buf;
-    int fd_flags = fcntl(fd, F_GETFL, 0);
-    struct pollfd pfd;
-
-again:
-    *bufit = 0;
-    pfd.fd = fd;
-    pfd.events = POLLIN;
-    *err = errno = 0;
-    int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, timeout_ms));
-    if (ret < 0) {
-        ALOGE("poll() error\n");
-        *err = errno;
-        return NULL;
-    }
-    if (ret == 0) {
-        return NULL;
-    }
-
-    if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
-        ALOGW("RFCOMM poll() returned  success (%d), "
-             "but with an unexpected revents bitmask: %#x\n", ret, pfd.revents);
-        errno = EIO;
-        *err = errno;
-        return NULL;
-    }
-
-    while ((int)(bufit - buf) < (len - 1))
-    {
-        errno = 0;
-        int rc = TEMP_FAILURE_RETRY(read(fd, bufit, 1));
-
-        if (!rc)
-            break;
-
-        if (rc < 0) {
-            if (errno == EBUSY) {
-                ALOGI("read() error %s (%d): repeating read()...",
-                     strerror(errno), errno);
-                goto again;
-            }
-            *err = errno;
-            ALOGE("read() error %s (%d)", strerror(errno), errno);
-            return NULL;
-        }
-
-
-        if (*bufit=='\xd') {
-            break;
-        }
-
-        if (*bufit=='\xa')
-            bufit = buf;
-        else
-            bufit++;
-    }
-
-    *bufit = 0;
-
-    // According to ITU V.250 section 5.1, IA5 7 bit chars are used, 
-    //   the eighth bit or higher bits are ignored if they exists
-    // We mask out only eighth bit, no higher bit, since we do char
-    // string here, not wide char.
-    // We added this processing due to 2 real world problems.
-    // 1 BMW 2005 E46 which sends binary junk
-    // 2 Audi 2010 A3, dial command use 0xAD (soft-hyphen) as number 
-    //   formater, which was rejected by the AT handler
-    mask_eighth_bit(buf);
-
-    return buf;
-}
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mAddress = get_field(env, clazz, "mAddress", "Ljava/lang/String;");
-    field_mTimeoutRemainingMs = get_field(env, clazz, "mTimeoutRemainingMs", "I");
-    field_mRfcommChannel = get_field(env, clazz, "mRfcommChannel", "I");
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object,
-                                       jint socketFd) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return;
-    }
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-    nat->address =
-        (jstring)env->NewGlobalRef(env->GetObjectField(object,
-                                                       field_mAddress));
-    nat->c_address = env->GetStringUTFChars(nat->address, NULL);
-    nat->rfcomm_channel = env->GetIntField(object, field_mRfcommChannel);
-    nat->rfcomm_sock = socketFd;
-    nat->rfcomm_connected = socketFd >= 0;
-    if (nat->rfcomm_connected)
-        ALOGI("%s: ALREADY CONNECTED!", __FUNCTION__);
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-        (native_data_t *)env->GetIntField(object, field_mNativeData);
-    env->ReleaseStringUTFChars(nat->address, nat->c_address);
-    env->DeleteGlobalRef(nat->address);
-    if (nat)
-        free(nat);
-#endif
-}
-
-static jboolean connectNative(JNIEnv *env, jobject obj)
-{
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    int lm;
-    struct sockaddr_rc addr;
-    native_data_t *nat = get_native_data(env, obj);
-
-    nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-
-    if (nat->rfcomm_sock < 0) {
-        ALOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__,
-             strerror(errno));
-        return JNI_FALSE;
-    }
-
-    if (debug_no_encrypt()) {
-        lm = RFCOMM_LM_AUTH;
-    } else {
-        lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
-    }
-
-    if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm,
-                sizeof(lm)) < 0) {
-        ALOGE("%s: Can't set RFCOMM link mode", __FUNCTION__);
-        close(nat->rfcomm_sock);
-        return JNI_FALSE;
-    }
-
-    memset(&addr, 0, sizeof(struct sockaddr_rc));
-    get_bdaddr(nat->c_address, &addr.rc_bdaddr);
-    addr.rc_channel = nat->rfcomm_channel;
-    addr.rc_family = AF_BLUETOOTH;
-    nat->rfcomm_connected = 0;
-    while (nat->rfcomm_connected == 0) {
-        if (connect(nat->rfcomm_sock, (struct sockaddr *)&addr,
-                      sizeof(addr)) < 0) {
-            if (errno == EINTR) continue;
-            ALOGE("%s: connect() failed: %s\n", __FUNCTION__, strerror(errno));
-            close(nat->rfcomm_sock);
-            nat->rfcomm_sock = -1;
-            return JNI_FALSE;
-        } else {
-            nat->rfcomm_connected = 1;
-        }
-    }
-
-    return JNI_TRUE;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jint connectAsyncNative(JNIEnv *env, jobject obj) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    struct sockaddr_rc addr;
-    native_data_t *nat = get_native_data(env, obj);
-
-    if (nat->rfcomm_connected) {
-        ALOGV("RFCOMM socket is already connected or connection is in progress.");
-        return 0;
-    }
-
-    if (nat->rfcomm_sock < 0) {
-        int lm;
-
-        nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-        if (nat->rfcomm_sock < 0) {
-            ALOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__,
-                 strerror(errno));
-            return -1;
-        }
-
-        if (debug_no_encrypt()) {
-            lm = RFCOMM_LM_AUTH;
-        } else {
-            lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
-        }
-
-        if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm,
-                    sizeof(lm)) < 0) {
-            ALOGE("%s: Can't set RFCOMM link mode", __FUNCTION__);
-            close(nat->rfcomm_sock);
-            return -1;
-        }
-        ALOGI("Created RFCOMM socket fd %d.", nat->rfcomm_sock);
-    }
-
-    memset(&addr, 0, sizeof(struct sockaddr_rc));
-    get_bdaddr(nat->c_address, &addr.rc_bdaddr);
-    addr.rc_channel = nat->rfcomm_channel;
-    addr.rc_family = AF_BLUETOOTH;
-    if (nat->rfcomm_sock_flags >= 0) {
-        nat->rfcomm_sock_flags = fcntl(nat->rfcomm_sock, F_GETFL, 0);
-        if (fcntl(nat->rfcomm_sock,
-                  F_SETFL, nat->rfcomm_sock_flags | O_NONBLOCK) >= 0) {
-            int rc;
-            nat->rfcomm_connected = 0;
-            errno = 0;
-            rc = connect(nat->rfcomm_sock,
-                        (struct sockaddr *)&addr,
-                         sizeof(addr));
-
-            if (rc >= 0) {
-                nat->rfcomm_connected = 1;
-                ALOGI("async connect successful");
-                return 0;
-            }
-            else if (rc < 0) {
-                if (errno == EINPROGRESS || errno == EAGAIN)
-                {
-                    ALOGI("async connect is in progress (%s)",
-                         strerror(errno));
-                    nat->rfcomm_connected = -1;
-                    return 0;
-                }
-                else
-                {
-                    ALOGE("async connect error: %s (%d)", strerror(errno), errno);
-                    close(nat->rfcomm_sock);
-                    nat->rfcomm_sock = -1;
-                    return -errno;
-                }
-            }
-        } // fcntl(nat->rfcomm_sock ...)
-    } // if (nat->rfcomm_sock_flags >= 0)
-#endif
-    return -1;
-}
-
-static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj,
-                                           jint timeout_ms) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    struct sockaddr_rc addr;
-    native_data_t *nat = get_native_data(env, obj);
-
-    env->SetIntField(obj, field_mTimeoutRemainingMs, timeout_ms);
-
-    if (nat->rfcomm_connected > 0) {
-        ALOGI("RFCOMM is already connected!");
-        return 1;
-    }
-
-    if (nat->rfcomm_sock >= 0 && nat->rfcomm_connected == 0) {
-        ALOGI("Re-opening RFCOMM socket.");
-        close(nat->rfcomm_sock);
-        nat->rfcomm_sock = -1;
-    }
-    int ret = connectAsyncNative(env, obj);
-
-    if (ret < 0) {
-        ALOGI("Failed to re-open RFCOMM socket!");
-        return ret;
-    }
-
-    if (nat->rfcomm_sock >= 0) {
-        /* Do an asynchronous select() */
-        int n;
-        fd_set rset, wset;
-        struct timeval to;
-
-        FD_ZERO(&rset);
-        FD_ZERO(&wset);
-        FD_SET(nat->rfcomm_sock, &rset);
-        FD_SET(nat->rfcomm_sock, &wset);
-        if (timeout_ms >= 0) {
-            to.tv_sec = timeout_ms / 1000;
-            to.tv_usec = 1000 * (timeout_ms % 1000);
-        }
-        n = select(nat->rfcomm_sock + 1,
-                   &rset,
-                   &wset,
-                   NULL,
-                   (timeout_ms < 0 ? NULL : &to));
-
-        if (timeout_ms > 0) {
-            jint remaining = to.tv_sec*1000 + to.tv_usec/1000;
-            ALOGV("Remaining time %ldms", (long)remaining);
-            env->SetIntField(obj, field_mTimeoutRemainingMs,
-                             remaining);
-        }
-
-        if (n <= 0) {
-            if (n < 0)  {
-                ALOGE("select() on RFCOMM socket: %s (%d)",
-                     strerror(errno),
-                     errno);
-                return -errno;
-            }
-            return 0;
-        }
-        /* n must be equal to 1 and either rset or wset must have the
-           file descriptor set. */
-        ALOGV("select() returned %d.", n);
-        if (FD_ISSET(nat->rfcomm_sock, &rset) ||
-            FD_ISSET(nat->rfcomm_sock, &wset))
-        {
-            /* A trial async read() will tell us if everything is OK. */
-            {
-                char ch;
-                errno = 0;
-                int nr = TEMP_FAILURE_RETRY(read(nat->rfcomm_sock, &ch, 1));
-                /* It should be that nr != 1 because we just opened a socket
-                   and we haven't sent anything over it for the other side to
-                   respond... but one can't be paranoid enough.
-                */
-                if (nr >= 0 || errno != EAGAIN) {
-                    ALOGE("RFCOMM async connect() error: %s (%d), nr = %d\n",
-                         strerror(errno),
-                         errno,
-                         nr);
-                    /* Clear the rfcomm_connected flag to cause this function
-                       to re-create the socket and re-attempt the connect()
-                       the next time it is called.
-                    */
-                    nat->rfcomm_connected = 0;
-                    /* Restore the blocking properties of the socket. */
-                    fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags);
-                    close(nat->rfcomm_sock);
-                    nat->rfcomm_sock = -1;
-                    return -errno;
-                }
-            }
-            /* Restore the blocking properties of the socket. */
-            fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags);
-            ALOGI("Successful RFCOMM socket connect.");
-            nat->rfcomm_connected = 1;
-            return 1;
-        }
-    }
-    else ALOGE("RFCOMM socket file descriptor %d is bad!",
-              nat->rfcomm_sock);
-#endif
-    return -1;
-}
-
-static void disconnectNative(JNIEnv *env, jobject obj) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, obj);
-    if (nat->rfcomm_sock >= 0) {
-        close(nat->rfcomm_sock);
-        nat->rfcomm_sock = -1;
-        nat->rfcomm_connected = 0;
-    }
-#endif
-}
-
-static void pretty_log_urc(const char *urc) {
-    size_t i;
-    bool in_line_break = false;
-    char *buf = (char *)calloc(strlen(urc) + 1, sizeof(char));
-
-    strcpy(buf, urc);
-    for (i = 0; i < strlen(buf); i++) {
-        switch(buf[i]) {
-        case '\r':
-        case '\n':
-            in_line_break = true;
-            buf[i] = ' ';
-            break;
-        default:
-            if (in_line_break) {
-                in_line_break = false;
-                buf[i-1] = '\n';
-            }
-        }
-    }
-    IF_ALOGV() ALOG(LOG_VERBOSE, "Bluetooth AT sent", "%s", buf);
-
-    free(buf);
-}
-
-static jboolean sendURCNative(JNIEnv *env, jobject obj, jstring urc) {
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, obj);
-    if (nat->rfcomm_connected) {
-        const char *c_urc = env->GetStringUTFChars(urc, NULL);
-        jboolean ret = send_line(nat->rfcomm_sock, c_urc) == 0 ? JNI_TRUE : JNI_FALSE;
-        if (ret == JNI_TRUE) pretty_log_urc(c_urc);
-        env->ReleaseStringUTFChars(urc, c_urc);
-        return ret;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jstring readNative(JNIEnv *env, jobject obj, jint timeout_ms) {
-#ifdef HAVE_BLUETOOTH
-    {
-        native_data_t *nat = get_native_data(env, obj);
-        if (nat->rfcomm_connected) {
-            char buf[256];
-            const char *ret = get_line(nat->rfcomm_sock,
-                                       buf, sizeof(buf),
-                                       timeout_ms,
-                                       &nat->last_read_err);
-            return ret ? env->NewStringUTF(ret) : NULL;
-        }
-        return NULL;
-    }
-#else
-    return NULL;
-#endif
-}
-
-static jint getLastReadStatusNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    {
-        native_data_t *nat = get_native_data(env, obj);
-        if (nat->rfcomm_connected)
-            return (jint)nat->last_read_err;
-        return 0;
-    }
-#else
-    return 0;
-#endif
-}
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-    {"classInitNative", "()V", (void*)classInitNative},
-    {"initializeNativeDataNative", "(I)V", (void *)initializeNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"connectNative", "()Z", (void *)connectNative},
-    {"connectAsyncNative", "()I", (void *)connectAsyncNative},
-    {"waitForAsyncConnectNative", "(I)I", (void *)waitForAsyncConnectNative},
-    {"disconnectNative", "()V", (void *)disconnectNative},
-    {"sendURCNative", "(Ljava/lang/String;)Z", (void *)sendURCNative},
-    {"readNative", "(I)Ljava/lang/String;", (void *)readNative},
-    {"getLastReadStatusNative", "()I", (void *)getLastReadStatusNative},
-};
-
-int register_android_bluetooth_HeadsetBase(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-            "android/bluetooth/HeadsetBase", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_bluetooth_c.c b/core/jni/android_bluetooth_c.c
deleted file mode 100644
index b4c6727..0000000
--- a/core/jni/android_bluetooth_c.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifdef HAVE_BLUETOOTH
-
-#include "android_bluetooth_c.h"
-
-/*
- * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
- * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
- * is not valid C++ code.
- */
-bdaddr_t android_bluetooth_bdaddr_any(void)
-{
-  bdaddr_t any = *BDADDR_ANY;
-  return any;
-}
-#endif
diff --git a/core/jni/android_bluetooth_c.h b/core/jni/android_bluetooth_c.h
deleted file mode 100644
index e890244..0000000
--- a/core/jni/android_bluetooth_c.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_BLUETOOTH_C_H
-#define ANDROID_BLUETOOTH_C_H
-#ifdef HAVE_BLUETOOTH
-
-#include <bluetooth/bluetooth.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
- * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
- * is not valid C++ code.
- */
-bdaddr_t android_bluetooth_bdaddr_any(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*HAVE_BLUETOOTH*/
-#endif /*ANDROID_BLUETOOTH_C_H*/
diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp
deleted file mode 100644
index 5cdaa6c..0000000
--- a/core/jni/android_bluetooth_common.cpp
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "bluetooth_common.cpp"
-
-#include "android_bluetooth_common.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <cutils/properties.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-
-static Properties remote_device_properties[] = {
-    {"Address",  DBUS_TYPE_STRING},
-    {"Name", DBUS_TYPE_STRING},
-    {"Icon", DBUS_TYPE_STRING},
-    {"Class", DBUS_TYPE_UINT32},
-    {"UUIDs", DBUS_TYPE_ARRAY},
-    {"Services", DBUS_TYPE_ARRAY},
-    {"Paired", DBUS_TYPE_BOOLEAN},
-    {"Connected", DBUS_TYPE_BOOLEAN},
-    {"Trusted", DBUS_TYPE_BOOLEAN},
-    {"Blocked", DBUS_TYPE_BOOLEAN},
-    {"Alias", DBUS_TYPE_STRING},
-    {"Nodes", DBUS_TYPE_ARRAY},
-    {"Adapter", DBUS_TYPE_OBJECT_PATH},
-    {"LegacyPairing", DBUS_TYPE_BOOLEAN},
-    {"RSSI", DBUS_TYPE_INT16},
-    {"TX", DBUS_TYPE_UINT32},
-    {"Broadcaster", DBUS_TYPE_BOOLEAN}
-};
-
-static Properties adapter_properties[] = {
-    {"Address", DBUS_TYPE_STRING},
-    {"Name", DBUS_TYPE_STRING},
-    {"Class", DBUS_TYPE_UINT32},
-    {"Powered", DBUS_TYPE_BOOLEAN},
-    {"Discoverable", DBUS_TYPE_BOOLEAN},
-    {"DiscoverableTimeout", DBUS_TYPE_UINT32},
-    {"Pairable", DBUS_TYPE_BOOLEAN},
-    {"PairableTimeout", DBUS_TYPE_UINT32},
-    {"Discovering", DBUS_TYPE_BOOLEAN},
-    {"Devices", DBUS_TYPE_ARRAY},
-    {"UUIDs", DBUS_TYPE_ARRAY},
-};
-
-static Properties input_properties[] = {
-    {"Connected", DBUS_TYPE_BOOLEAN},
-};
-
-static Properties pan_properties[] = {
-    {"Connected", DBUS_TYPE_BOOLEAN},
-    {"Interface", DBUS_TYPE_STRING},
-    {"UUID", DBUS_TYPE_STRING},
-};
-
-static Properties health_device_properties[] = {
-    {"MainChannel", DBUS_TYPE_OBJECT_PATH},
-};
-
-static Properties health_channel_properties[] = {
-    {"Type", DBUS_TYPE_STRING},
-    {"Device", DBUS_TYPE_OBJECT_PATH},
-    {"Application", DBUS_TYPE_OBJECT_PATH},
-};
-
-typedef union {
-    char *str_val;
-    int int_val;
-    char **array_val;
-} property_value;
-
-jfieldID get_field(JNIEnv *env, jclass clazz, const char *member,
-                   const char *mtype) {
-    jfieldID field = env->GetFieldID(clazz, member, mtype);
-    if (field == NULL) {
-        ALOGE("Can't find member %s", member);
-    }
-    return field;
-}
-
-typedef struct {
-    void (*user_cb)(DBusMessage *, void *, void *);
-    void *user;
-    void *nat;
-    JNIEnv *env;
-} dbus_async_call_t;
-
-void dbus_func_args_async_callback(DBusPendingCall *call, void *data) {
-
-    dbus_async_call_t *req = (dbus_async_call_t *)data;
-    DBusMessage *msg;
-
-    /* This is guaranteed to be non-NULL, because this function is called only
-       when once the remote method invokation returns. */
-    msg = dbus_pending_call_steal_reply(call);
-
-    if (msg) {
-        if (req->user_cb) {
-            // The user may not deref the message object.
-            req->user_cb(msg, req->user, req->nat);
-        }
-        dbus_message_unref(msg);
-    }
-
-    //dbus_message_unref(req->method);
-    dbus_pending_call_cancel(call);
-    dbus_pending_call_unref(call);
-    free(req);
-}
-
-static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
-                                        DBusConnection *conn,
-                                        int timeout_ms,
-                                        void (*user_cb)(DBusMessage *,
-                                                        void *,
-                                                        void*),
-                                        void *user,
-                                        void *nat,
-                                        const char *path,
-                                        const char *ifc,
-                                        const char *func,
-                                        int first_arg_type,
-                                        va_list args) {
-    DBusMessage *msg = NULL;
-    const char *name;
-    dbus_async_call_t *pending;
-    dbus_bool_t reply = FALSE;
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
-
-    if (msg == NULL) {
-        ALOGE("Could not allocate D-Bus message object!");
-        goto done;
-    }
-
-    /* append arguments */
-    if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
-        ALOGE("Could not append argument to method call!");
-        goto done;
-    }
-
-    /* Make the call. */
-    pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t));
-    if (pending) {
-        DBusPendingCall *call;
-
-        pending->env = env;
-        pending->user_cb = user_cb;
-        pending->user = user;
-        pending->nat = nat;
-        //pending->method = msg;
-
-        reply = dbus_connection_send_with_reply(conn, msg,
-                                                &call,
-                                                timeout_ms);
-        if (reply == TRUE) {
-            dbus_pending_call_set_notify(call,
-                                         dbus_func_args_async_callback,
-                                         pending,
-                                         NULL);
-        }
-    }
-
-done:
-    if (msg) dbus_message_unref(msg);
-    return reply;
-}
-
-dbus_bool_t dbus_func_args_async(JNIEnv *env,
-                                 DBusConnection *conn,
-                                 int timeout_ms,
-                                 void (*reply)(DBusMessage *, void *, void*),
-                                 void *user,
-                                 void *nat,
-                                 const char *path,
-                                 const char *ifc,
-                                 const char *func,
-                                 int first_arg_type,
-                                 ...) {
-    dbus_bool_t ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-
-    ret = dbus_func_args_async_valist(env, conn,
-                                      timeout_ms,
-                                      reply, user, nat,
-                                      path, ifc, func,
-                                      first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-// If err is NULL, then any errors will be ALOGE'd, and free'd and the reply
-// will be NULL.
-// If err is not NULL, then it is assumed that dbus_error_init was already
-// called, and error's will be returned to the caller without logging. The
-// return value is NULL iff an error was set. The client must free the error if
-// set.
-DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env,
-                                            DBusConnection *conn,
-                                            int timeout_ms,
-                                            DBusError *err,
-                                            const char *path,
-                                            const char *ifc,
-                                            const char *func,
-                                            int first_arg_type,
-                                            va_list args) {
-
-    DBusMessage *msg = NULL, *reply = NULL;
-    const char *name;
-    bool return_error = (err != NULL);
-
-    if (!return_error) {
-        err = (DBusError*)malloc(sizeof(DBusError));
-        dbus_error_init(err);
-    }
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
-
-    if (msg == NULL) {
-        ALOGE("Could not allocate D-Bus message object!");
-        goto done;
-    }
-
-    /* append arguments */
-    if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
-        ALOGE("Could not append argument to method call!");
-        goto done;
-    }
-
-    /* Make the call. */
-    reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err);
-    if (!return_error && dbus_error_is_set(err)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg);
-    }
-
-done:
-    if (!return_error) {
-        free(err);
-    }
-    if (msg) dbus_message_unref(msg);
-    return reply;
-}
-
-DBusMessage * dbus_func_args_timeout(JNIEnv *env,
-                                     DBusConnection *conn,
-                                     int timeout_ms,
-                                     const char *path,
-                                     const char *ifc,
-                                     const char *func,
-                                     int first_arg_type,
-                                     ...) {
-    DBusMessage *ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-    ret = dbus_func_args_timeout_valist(env, conn, timeout_ms, NULL,
-                                        path, ifc, func,
-                                        first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-DBusMessage * dbus_func_args(JNIEnv *env,
-                             DBusConnection *conn,
-                             const char *path,
-                             const char *ifc,
-                             const char *func,
-                             int first_arg_type,
-                             ...) {
-    DBusMessage *ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-    ret = dbus_func_args_timeout_valist(env, conn, -1, NULL,
-                                        path, ifc, func,
-                                        first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-DBusMessage * dbus_func_args_error(JNIEnv *env,
-                                   DBusConnection *conn,
-                                   DBusError *err,
-                                   const char *path,
-                                   const char *ifc,
-                                   const char *func,
-                                   int first_arg_type,
-                                   ...) {
-    DBusMessage *ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-    ret = dbus_func_args_timeout_valist(env, conn, -1, err,
-                                        path, ifc, func,
-                                        first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jint ret = -1;
-
-    dbus_error_init(&err);
-    if (!dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_UNIX_FD, &ret,
-                               DBUS_TYPE_INVALID)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-    return ret;
-}
-
-
-jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jint ret = -1;
-
-    dbus_error_init(&err);
-    if (!dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_INT32, &ret,
-                               DBUS_TYPE_INVALID)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-    return ret;
-}
-
-jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jint ret = -1;
-
-    dbus_error_init(&err);
-    if (!dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_UINT32, &ret,
-                               DBUS_TYPE_INVALID)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-    return ret;
-}
-
-jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jstring ret = NULL;
-    const char *name;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_STRING, &name,
-                               DBUS_TYPE_INVALID)) {
-        ret = env->NewStringUTF(name);
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-
-    return ret;
-}
-
-jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply) {
-    DBusError err;
-    jboolean ret = JNI_FALSE;
-    dbus_bool_t val = FALSE;
-
-    dbus_error_init(&err);
-
-    /* Check the return value. */
-    if (dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_BOOLEAN, &val,
-                               DBUS_TYPE_INVALID)) {
-        ret = val == TRUE ? JNI_TRUE : JNI_FALSE;
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return ret;
-}
-
-static void set_object_array_element(JNIEnv *env, jobjectArray strArray,
-                                     const char *value, int index) {
-    jstring obj;
-    obj = env->NewStringUTF(value);
-    env->SetObjectArrayElement(strArray, index, obj);
-    env->DeleteLocalRef(obj);
-}
-
-jobjectArray dbus_returns_array_of_object_path(JNIEnv *env,
-                                               DBusMessage *reply) {
-
-    DBusError err;
-    char **list;
-    int i, len;
-    jobjectArray strArray = NULL;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args (reply,
-                               &err,
-                               DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
-                               &list, &len,
-                               DBUS_TYPE_INVALID)) {
-        jclass stringClass;
-        jstring classNameStr;
-
-        stringClass = env->FindClass("java/lang/String");
-        strArray = env->NewObjectArray(len, stringClass, NULL);
-
-        for (i = 0; i < len; i++)
-            set_object_array_element(env, strArray, list[i], i);
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return strArray;
-}
-
-jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    char **list;
-    int i, len;
-    jobjectArray strArray = NULL;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args (reply,
-                               &err,
-                               DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-                               &list, &len,
-                               DBUS_TYPE_INVALID)) {
-        jclass stringClass;
-        jstring classNameStr;
-
-        //ALOGV("%s: there are %d elements in string array!", __FUNCTION__, len);
-
-        stringClass = env->FindClass("java/lang/String");
-        strArray = env->NewObjectArray(len, stringClass, NULL);
-
-        for (i = 0; i < len; i++)
-            set_object_array_element(env, strArray, list[i], i);
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return strArray;
-}
-
-jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    int i, len;
-    jbyte *list;
-    jbyteArray byteArray = NULL;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args(reply, &err,
-                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &list, &len,
-                              DBUS_TYPE_INVALID)) {
-        //ALOGV("%s: there are %d elements in byte array!", __FUNCTION__, len);
-        byteArray = env->NewByteArray(len);
-        if (byteArray)
-            env->SetByteArrayRegion(byteArray, 0, len, list);
-
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return byteArray;
-}
-
-void append_variant(DBusMessageIter *iter, int type, void *val)
-{
-    DBusMessageIter value_iter;
-    char var_type[2] = { type, '\0'};
-    dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, var_type, &value_iter);
-    dbus_message_iter_append_basic(&value_iter, type, val);
-    dbus_message_iter_close_container(iter, &value_iter);
-}
-
-static void dict_append_entry(DBusMessageIter *dict,
-                        const char *key, int type, void *val)
-{
-        DBusMessageIter dict_entry;
-        dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
-                                                        NULL, &dict_entry);
-
-        dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
-        append_variant(&dict_entry, type, val);
-        dbus_message_iter_close_container(dict, &dict_entry);
-}
-
-static void append_dict_valist(DBusMessageIter *iterator, const char *first_key,
-                                va_list var_args)
-{
-        DBusMessageIter dict;
-        int val_type;
-        const char *val_key;
-        void *val;
-
-        dbus_message_iter_open_container(iterator, DBUS_TYPE_ARRAY,
-                        DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-                        DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-                        DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-        val_key = first_key;
-        while (val_key) {
-                val_type = va_arg(var_args, int);
-                val = va_arg(var_args, void *);
-                dict_append_entry(&dict, val_key, val_type, val);
-                val_key = va_arg(var_args, char *);
-        }
-
-        dbus_message_iter_close_container(iterator, &dict);
-}
-
-void append_dict_args(DBusMessage *reply, const char *first_key, ...)
-{
-        DBusMessageIter iter;
-        va_list var_args;
-
-        dbus_message_iter_init_append(reply, &iter);
-
-        va_start(var_args, first_key);
-        append_dict_valist(&iter, first_key, var_args);
-        va_end(var_args);
-}
-
-
-int get_property(DBusMessageIter iter, Properties *properties,
-                  int max_num_properties, int *prop_index, property_value *value, int *len) {
-    DBusMessageIter prop_val, array_val_iter;
-    char *property = NULL;
-    uint32_t array_type;
-    char *str_val;
-    int i, j, type, int_val;
-
-    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-        return -1;
-    dbus_message_iter_get_basic(&iter, &property);
-    if (!dbus_message_iter_next(&iter))
-        return -1;
-    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
-        return -1;
-    for (i = 0; i <  max_num_properties; i++) {
-        if (!strncmp(property, properties[i].name, strlen(property)))
-            break;
-    }
-    *prop_index = i;
-    if (i == max_num_properties)
-        return -1;
-
-    dbus_message_iter_recurse(&iter, &prop_val);
-    type = properties[*prop_index].type;
-    if (dbus_message_iter_get_arg_type(&prop_val) != type) {
-        ALOGE("Property type mismatch in get_property: %d, expected:%d, index:%d",
-             dbus_message_iter_get_arg_type(&prop_val), type, *prop_index);
-        return -1;
-    }
-
-    switch(type) {
-    case DBUS_TYPE_STRING:
-    case DBUS_TYPE_OBJECT_PATH:
-        dbus_message_iter_get_basic(&prop_val, &value->str_val);
-        *len = 1;
-        break;
-    case DBUS_TYPE_UINT32:
-    case DBUS_TYPE_INT16:
-    case DBUS_TYPE_BOOLEAN:
-        dbus_message_iter_get_basic(&prop_val, &int_val);
-        value->int_val = int_val;
-        *len = 1;
-        break;
-    case DBUS_TYPE_ARRAY:
-        dbus_message_iter_recurse(&prop_val, &array_val_iter);
-        array_type = dbus_message_iter_get_arg_type(&array_val_iter);
-        *len = 0;
-        value->array_val = NULL;
-        if (array_type == DBUS_TYPE_OBJECT_PATH ||
-            array_type == DBUS_TYPE_STRING){
-            j = 0;
-            do {
-               j ++;
-            } while(dbus_message_iter_next(&array_val_iter));
-            dbus_message_iter_recurse(&prop_val, &array_val_iter);
-            // Allocate  an array of char *
-            *len = j;
-            char **tmp = (char **)malloc(sizeof(char *) * *len);
-            if (!tmp)
-                return -1;
-            j = 0;
-            do {
-               dbus_message_iter_get_basic(&array_val_iter, &tmp[j]);
-               j ++;
-            } while(dbus_message_iter_next(&array_val_iter));
-            value->array_val = tmp;
-        }
-        break;
-    default:
-        return -1;
-    }
-    return 0;
-}
-
-void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property,
-                       property_value *value, int len, int *array_index ) {
-    char **prop_val = NULL;
-    char buf[32] = {'\0'}, buf1[32] = {'\0'};
-    int i;
-
-    char *name = property->name;
-    int prop_type = property->type;
-
-    set_object_array_element(env, strArray, name, *array_index);
-    *array_index += 1;
-
-    if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) {
-        sprintf(buf, "%d", value->int_val);
-        set_object_array_element(env, strArray, buf, *array_index);
-        *array_index += 1;
-    } else if (prop_type == DBUS_TYPE_BOOLEAN) {
-        sprintf(buf, "%s", value->int_val ? "true" : "false");
-
-        set_object_array_element(env, strArray, buf, *array_index);
-        *array_index += 1;
-    } else if (prop_type == DBUS_TYPE_ARRAY) {
-        // Write the length first
-        sprintf(buf1, "%d", len);
-        set_object_array_element(env, strArray, buf1, *array_index);
-        *array_index += 1;
-
-        prop_val = value->array_val;
-        for (i = 0; i < len; i++) {
-            set_object_array_element(env, strArray, prop_val[i], *array_index);
-            *array_index += 1;
-        }
-    } else {
-        set_object_array_element(env, strArray, (const char *) value->str_val, *array_index);
-        *array_index += 1;
-    }
-}
-
-jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
-                              const int max_num_properties) {
-    DBusMessageIter dict_entry, dict;
-    jobjectArray strArray = NULL;
-    property_value value;
-    int i, size = 0,array_index = 0;
-    int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type;
-    struct {
-        property_value value;
-        int len;
-        bool used;
-    } values[max_num_properties];
-    int t, j;
-
-    jclass stringClass = env->FindClass("java/lang/String");
-    DBusError err;
-    dbus_error_init(&err);
-
-    for (i = 0; i < max_num_properties; i++) {
-        values[i].used = false;
-    }
-
-    if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
-        goto failure;
-    dbus_message_iter_recurse(iter, &dict);
-    do {
-        len = 0;
-        if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY)
-            goto failure;
-        dbus_message_iter_recurse(&dict, &dict_entry);
-
-        if (!get_property(dict_entry, properties, max_num_properties, &prop_index,
-                          &value, &len)) {
-            size += 2;
-            if (properties[prop_index].type == DBUS_TYPE_ARRAY)
-                size += len;
-            values[prop_index].value = value;
-            values[prop_index].len = len;
-            values[prop_index].used = true;
-        } else {
-            goto failure;
-        }
-    } while(dbus_message_iter_next(&dict));
-
-    strArray = env->NewObjectArray(size, stringClass, NULL);
-
-    for (i = 0; i < max_num_properties; i++) {
-        if (values[i].used) {
-            create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len,
-                              &array_index);
-
-            if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used
-                   && values[i].value.array_val != NULL)
-                free(values[i].value.array_val);
-        }
-
-    }
-    return strArray;
-
-failure:
-    if (dbus_error_is_set(&err))
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    for (i = 0; i < max_num_properties; i++)
-        if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true
-                                        && values[i].value.array_val != NULL)
-            free(values[i].value.array_val);
-    return NULL;
-}
-
-jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg,
-                           Properties *properties, int max_num_properties) {
-    DBusMessageIter iter;
-    DBusError err;
-    jobjectArray strArray = NULL;
-    jclass stringClass= env->FindClass("java/lang/String");
-    int len = 0, prop_index = -1;
-    int array_index = 0, size = 0;
-    property_value value;
-
-    dbus_error_init(&err);
-    if (!dbus_message_iter_init(msg, &iter))
-        goto failure;
-
-    if (!get_property(iter, properties, max_num_properties,
-                      &prop_index, &value, &len)) {
-        size += 2;
-        if (properties[prop_index].type == DBUS_TYPE_ARRAY)
-            size += len;
-        strArray = env->NewObjectArray(size, stringClass, NULL);
-
-        create_prop_array(env, strArray, &properties[prop_index],
-                          &value, len, &array_index);
-
-        if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL)
-             free(value.array_val);
-
-        return strArray;
-    }
-failure:
-    LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-    return NULL;
-}
-
-jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &adapter_properties,
-                    sizeof(adapter_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &remote_device_properties,
-                    sizeof(remote_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &input_properties,
-                    sizeof(input_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &pan_properties,
-                    sizeof(pan_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &adapter_properties,
-                            sizeof(adapter_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &remote_device_properties,
-                          sizeof(remote_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &input_properties,
-                          sizeof(input_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &health_device_properties,
-                          sizeof(health_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &health_device_properties,
-                    sizeof(health_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &health_channel_properties,
-                          sizeof(health_channel_properties) / sizeof(Properties));
-}
-
-int get_bdaddr(const char *str, bdaddr_t *ba) {
-    char *d = ((char *)ba) + 5, *endp;
-    int i;
-    for(i = 0; i < 6; i++) {
-        *d-- = strtol(str, &endp, 16);
-        if (*endp != ':' && i != 5) {
-            memset(ba, 0, sizeof(bdaddr_t));
-            return -1;
-        }
-        str = endp + 1;
-    }
-    return 0;
-}
-
-void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
-    const uint8_t *b = (const uint8_t *)ba;
-    sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-            b[5], b[4], b[3], b[2], b[1], b[0]);
-}
-
-bool debug_no_encrypt() {
-    return false;
-#if 0
-    char value[PROPERTY_VALUE_MAX] = "";
-
-    property_get("debug.bt.no_encrypt", value, "");
-    if (!strncmp("true", value, PROPERTY_VALUE_MAX) ||
-        !strncmp("1", value, PROPERTY_VALUE_MAX)) {
-        ALOGD("mandatory bluetooth encryption disabled");
-        return true;
-    } else {
-        return false;
-    }
-#endif
-}
-#endif
-
-} /* namespace android */
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
deleted file mode 100644
index daf4bb2..0000000
--- a/core/jni/android_bluetooth_common.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_BLUETOOTH_COMMON_H
-#define ANDROID_BLUETOOTH_COMMON_H
-
-// Set to 0 to enable verbose bluetooth logging
-#define LOG_NDEBUG 1
-
-#include "jni.h"
-#include "utils/Log.h"
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <sys/poll.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#include <bluetooth/bluetooth.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-#define BLUEZ_DBUS_BASE_PATH      "/org/bluez"
-#define BLUEZ_DBUS_BASE_IFC       "org.bluez"
-#define BLUEZ_ERROR_IFC           "org.bluez.Error"
-
-// It would be nicer to retrieve this from bluez using GetDefaultAdapter,
-// but this is only possible when the adapter is up (and hcid is running).
-// It is much easier just to hardcode bluetooth adapter to hci0
-#define BLUETOOTH_ADAPTER_HCI_NUM 0
-#define BLUEZ_ADAPTER_OBJECT_NAME BLUEZ_DBUS_BASE_PATH "/hci0"
-
-#define BTADDR_SIZE 18   // size of BT address character array (including null)
-
-// size of the dbus event loops pollfd structure, hopefully never to be grown
-#define DEFAULT_INITIAL_POLLFD_COUNT 8
-
-jfieldID get_field(JNIEnv *env,
-                   jclass clazz,
-                   const char *member,
-                   const char *mtype);
-
-// ALOGE and free a D-Bus error
-// Using #define so that __FUNCTION__ resolves usefully
-#define LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg) \
-    {   ALOGE("%s: D-Bus error in %s: %s (%s)", __FUNCTION__, \
-        dbus_message_get_member((msg)), (err)->name, (err)->message); \
-         dbus_error_free((err)); }
-#define LOG_AND_FREE_DBUS_ERROR(err) \
-    {   ALOGE("%s: D-Bus error: %s (%s)", __FUNCTION__, \
-        (err)->name, (err)->message); \
-        dbus_error_free((err)); }
-
-struct event_loop_native_data_t {
-    DBusConnection *conn;
-    const char *adapter;
-
-    /* protects the thread */
-    pthread_mutex_t thread_mutex;
-    pthread_t thread;
-    /* our comms socket */
-    /* mem for the list of sockets to listen to */
-    struct pollfd *pollData;
-    int pollMemberCount;
-    int pollDataSize;
-    /* mem for matching set of dbus watch ptrs */
-    DBusWatch **watchData;
-    /* pair of sockets for event loop control, Reader and Writer */
-    int controlFdR;
-    int controlFdW;
-    /* our vm and env Version for future env generation */
-    JavaVM *vm;
-    int envVer;
-    /* reference to our java self */
-    jobject me;
-    /* flag to indicate if the event loop thread is running */
-    bool running;
-};
-
-struct _Properties {
-    char name[32];
-    int type;
-};
-typedef struct _Properties Properties;
-
-dbus_bool_t dbus_func_args_async(JNIEnv *env,
-                                 DBusConnection *conn,
-                                 int timeout_ms,
-                                 void (*reply)(DBusMessage *, void *, void *),
-                                 void *user,
-                                 void *nat,
-                                 const char *path,
-                                 const char *ifc,
-                                 const char *func,
-                                 int first_arg_type,
-                                 ...);
-
-DBusMessage * dbus_func_args(JNIEnv *env,
-                             DBusConnection *conn,
-                             const char *path,
-                             const char *ifc,
-                             const char *func,
-                             int first_arg_type,
-                             ...);
-
-DBusMessage * dbus_func_args_error(JNIEnv *env,
-                                   DBusConnection *conn,
-                                   DBusError *err,
-                                   const char *path,
-                                   const char *ifc,
-                                   const char *func,
-                                   int first_arg_type,
-                                   ...);
-
-DBusMessage * dbus_func_args_timeout(JNIEnv *env,
-                                     DBusConnection *conn,
-                                     int timeout_ms,
-                                     const char *path,
-                                     const char *ifc,
-                                     const char *func,
-                                     int first_arg_type,
-                                     ...);
-
-DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env,
-                                            DBusConnection *conn,
-                                            int timeout_ms,
-                                            DBusError *err,
-                                            const char *path,
-                                            const char *ifc,
-                                            const char *func,
-                                            int first_arg_type,
-                                            va_list args);
-
-jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply);
-jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply);
-jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply);
-jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply);
-jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply);
-jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply);
-jobjectArray dbus_returns_array_of_object_path(JNIEnv *env, DBusMessage *reply);
-jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply);
-
-jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
-                              const int max_num_properties);
-jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg,
-                                   Properties *properties, int max_num_properties);
-jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg);
-
-void append_dict_args(DBusMessage *reply, const char *first_key, ...);
-void append_variant(DBusMessageIter *iter, int type, void *val);
-int get_bdaddr(const char *str, bdaddr_t *ba);
-void get_bdaddr_as_string(const bdaddr_t *ba, char *str);
-
-bool debug_no_encrypt();
-
-
-// Result codes from Bluez DBus calls
-#define BOND_RESULT_ERROR                      -1
-#define BOND_RESULT_SUCCESS                     0
-#define BOND_RESULT_AUTH_FAILED                 1
-#define BOND_RESULT_AUTH_REJECTED               2
-#define BOND_RESULT_AUTH_CANCELED               3
-#define BOND_RESULT_REMOTE_DEVICE_DOWN          4
-#define BOND_RESULT_DISCOVERY_IN_PROGRESS       5
-#define BOND_RESULT_AUTH_TIMEOUT                6
-#define BOND_RESULT_REPEATED_ATTEMPTS           7
-
-#define PAN_DISCONNECT_FAILED_NOT_CONNECTED  1000
-#define PAN_CONNECT_FAILED_ALREADY_CONNECTED 1001
-#define PAN_CONNECT_FAILED_ATTEMPT_FAILED    1002
-#define PAN_OPERATION_GENERIC_FAILURE        1003
-#define PAN_OPERATION_SUCCESS                1004
-
-#define INPUT_DISCONNECT_FAILED_NOT_CONNECTED  5000
-#define INPUT_CONNECT_FAILED_ALREADY_CONNECTED 5001
-#define INPUT_CONNECT_FAILED_ATTEMPT_FAILED    5002
-#define INPUT_OPERATION_GENERIC_FAILURE        5003
-#define INPUT_OPERATION_SUCCESS                5004
-
-#define HEALTH_OPERATION_SUCCESS               6000
-#define HEALTH_OPERATION_ERROR                 6001
-#define HEALTH_OPERATION_INVALID_ARGS          6002
-#define HEALTH_OPERATION_GENERIC_FAILURE       6003
-#define HEALTH_OPERATION_NOT_FOUND             6004
-#define HEALTH_OPERATION_NOT_ALLOWED           6005
-
-#endif
-} /* namespace android */
-
-#endif/*ANDROID_BLUETOOTH_COMMON_H*/
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 0f04e6f..c76cb64 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -242,7 +242,6 @@
         format,        // word length, PCM
         channels,
         frameCount,
-        (AudioRecord::record_flags) 0,  // flags
         recorderCallback,// callback_t
         lpCallbackData,// void* user
         0,             // notificationFrames,
@@ -517,7 +516,7 @@
             sampleRateInHertz,
             (audioFormat == javaAudioRecordFields.PCM16 ?
                 AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_8_BIT),
-            nbChannels);
+            audio_channel_in_mask_from_count(nbChannels));
 
     if (result == BAD_VALUE) {
         return 0;
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
new file mode 100644
index 0000000..c271aeb
--- /dev/null
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -0,0 +1,1247 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// This source file is automatically generated
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <EGL/egl.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <ui/ANativeObjectBase.h>
+
+static int initialized = 0;
+
+static jclass egldisplayClass;
+static jclass eglcontextClass;
+static jclass eglsurfaceClass;
+static jclass eglconfigClass;
+
+static jmethodID egldisplayGetHandleID;
+static jmethodID eglcontextGetHandleID;
+static jmethodID eglsurfaceGetHandleID;
+static jmethodID eglconfigGetHandleID;
+
+static jmethodID egldisplayConstructor;
+static jmethodID eglcontextConstructor;
+static jmethodID eglsurfaceConstructor;
+static jmethodID eglconfigConstructor;
+
+static jobject eglNoContextObject;
+static jobject eglNoDisplayObject;
+static jobject eglNoSurfaceObject;
+
+
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
+    egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
+    jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
+    eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
+    jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
+    eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
+    jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
+    eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+
+
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+
+
+    jclass eglClass = _env->FindClass("android/opengl/EGL14");
+    jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
+    _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject);
+
+    jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
+    _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject);
+
+    jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
+    _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject);
+}
+
+static void *
+fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) {
+    if (obj == NULL){
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Object is set to null.");
+    }
+
+    return (void*) (_env->CallIntMethod(obj, mid));
+}
+
+static jobject
+toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
+    if (cls == eglcontextClass &&
+       (EGLContext)handle == EGL_NO_CONTEXT) {
+           return eglNoContextObject;
+    }
+
+    if (cls == egldisplayClass &&
+       (EGLDisplay)handle == EGL_NO_DISPLAY) {
+           return eglNoDisplayObject;
+    }
+
+    if (cls == eglsurfaceClass &&
+       (EGLSurface)handle == EGL_NO_SURFACE) {
+           return eglNoSurfaceObject;
+    }
+
+    return _env->NewObject(cls, con, (jint)handle);
+}
+
+// --------------------------------------------------------------------------
+/* EGLint eglGetError ( void ) */
+static jint
+android_eglGetError
+  (JNIEnv *_env, jobject _this) {
+    EGLint _returnValue = (EGLint) 0;
+    _returnValue = eglGetError();
+    return _returnValue;
+}
+
+/* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
+static jobject
+android_eglGetDisplay
+  (JNIEnv *_env, jobject _this, jint display_id) {
+    EGLDisplay _returnValue = (EGLDisplay) 0;
+    _returnValue = eglGetDisplay(
+        (EGLNativeDisplayType)display_id
+    );
+    return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
+}
+
+/* EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor ) */
+static jboolean
+android_eglInitialize
+  (JNIEnv *_env, jobject _this, jobject dpy, jintArray major_ref, jint majorOffset, jintArray minor_ref, jint minorOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLint *major_base = (EGLint *) 0;
+    jint _majorRemaining;
+    EGLint *major = (EGLint *) 0;
+    EGLint *minor_base = (EGLint *) 0;
+    jint _minorRemaining;
+    EGLint *minor = (EGLint *) 0;
+
+    if (!major_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "major == null";
+        goto exit;
+    }
+    if (majorOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "majorOffset < 0";
+        goto exit;
+    }
+    _majorRemaining = _env->GetArrayLength(major_ref) - majorOffset;
+    if (_majorRemaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - majorOffset < 1 < needed";
+        goto exit;
+    }
+    major_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(major_ref, (jboolean *)0);
+    major = major_base + majorOffset;
+
+    if (!minor_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "minor == null";
+        goto exit;
+    }
+    if (minorOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "minorOffset < 0";
+        goto exit;
+    }
+    _minorRemaining = _env->GetArrayLength(minor_ref) - minorOffset;
+    if (_minorRemaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - minorOffset < 1 < needed";
+        goto exit;
+    }
+    minor_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(minor_ref, (jboolean *)0);
+    minor = minor_base + minorOffset;
+
+    _returnValue = eglInitialize(
+        (EGLDisplay)dpy_native,
+        (EGLint *)major,
+        (EGLint *)minor
+    );
+
+exit:
+    if (minor_base) {
+        _env->ReleasePrimitiveArrayCritical(minor_ref, minor_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (major_base) {
+        _env->ReleasePrimitiveArrayCritical(major_ref, major_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglTerminate ( EGLDisplay dpy ) */
+static jboolean
+android_eglTerminate
+  (JNIEnv *_env, jobject _this, jobject dpy) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+
+    _returnValue = eglTerminate(
+        (EGLDisplay)dpy_native
+    );
+    return _returnValue;
+}
+
+/* const char * eglQueryString ( EGLDisplay dpy, EGLint name ) */
+static jstring
+android_eglQueryString__Landroind_opengl_EGLDisplay_2I
+  (JNIEnv *_env, jobject _this, jobject dpy, jint name) {
+    const char* chars = (const char*) eglQueryString(
+        (EGLDisplay)fromEGLHandle(_env, egldisplayGetHandleID, dpy),
+        (EGLint)name
+    );
+    return _env->NewStringUTF(chars);
+}
+/* EGLBoolean eglGetConfigs ( EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config ) */
+static jboolean
+android_eglGetConfigs
+  (JNIEnv *_env, jobject _this, jobject dpy, jobjectArray configs_ref, jint configsOffset, jint config_size, jintArray num_config_ref, jint num_configOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    jint _configsRemaining;
+    EGLConfig *configs = (EGLConfig *) 0;
+    EGLint *num_config_base = (EGLint *) 0;
+    jint _num_configRemaining;
+    EGLint *num_config = (EGLint *) 0;
+
+    if (!configs_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configs == null";
+        goto exit;
+    }
+    if (configsOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configsOffset < 0";
+        goto exit;
+    }
+    _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
+    if (_configsRemaining < config_size) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - configsOffset < config_size < needed";
+        goto exit;
+    }
+    configs = new EGLConfig[_configsRemaining];
+
+    if (!num_config_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_config == null";
+        goto exit;
+    }
+    if (num_configOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_configOffset < 0";
+        goto exit;
+    }
+    _num_configRemaining = _env->GetArrayLength(num_config_ref) - num_configOffset;
+    num_config_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(num_config_ref, (jboolean *)0);
+    num_config = num_config_base + num_configOffset;
+
+    _returnValue = eglGetConfigs(
+        (EGLDisplay)dpy_native,
+        (EGLConfig *)configs,
+        (EGLint)config_size,
+        (EGLint *)num_config
+    );
+
+exit:
+    if (num_config_base) {
+        _env->ReleasePrimitiveArrayCritical(num_config_ref, num_config_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (configs) {
+        for (int i = 0; i < _configsRemaining; i++) {
+            jobject configs_new = toEGLHandle(_env, eglconfigClass, eglconfigConstructor, configs[i]);
+            _env->SetObjectArrayElement(configs_ref, i + configsOffset, configs_new);
+        }
+        delete[] configs;
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglChooseConfig ( EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config ) */
+static jboolean
+android_eglChooseConfig
+  (JNIEnv *_env, jobject _this, jobject dpy, jintArray attrib_list_ref, jint attrib_listOffset, jobjectArray configs_ref, jint configsOffset, jint config_size, jintArray num_config_ref, jint num_configOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _attrib_listRemaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    jint _configsRemaining;
+    EGLConfig *configs = (EGLConfig *) 0;
+    EGLint *num_config_base = (EGLint *) 0;
+    jint _num_configRemaining;
+    EGLint *num_config = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (attrib_listOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_listOffset < 0";
+        goto exit;
+    }
+    _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - attrib_listOffset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + attrib_listOffset;
+    attrib_list_sentinel = false;
+    for (int i = _attrib_listRemaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    if (!configs_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configs == null";
+        goto exit;
+    }
+    if (configsOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configsOffset < 0";
+        goto exit;
+    }
+    _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
+    if (_configsRemaining < config_size) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - configsOffset < config_size < needed";
+        goto exit;
+    }
+    configs = new EGLConfig[_configsRemaining];
+
+    if (!num_config_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_config == null";
+        goto exit;
+    }
+    if (num_configOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_configOffset < 0";
+        goto exit;
+    }
+    _num_configRemaining = _env->GetArrayLength(num_config_ref) - num_configOffset;
+    if (_num_configRemaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - num_configOffset < 1 < needed";
+        goto exit;
+    }
+    num_config_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(num_config_ref, (jboolean *)0);
+    num_config = num_config_base + num_configOffset;
+
+    _returnValue = eglChooseConfig(
+        (EGLDisplay)dpy_native,
+        (EGLint *)attrib_list,
+        (EGLConfig *)configs,
+        (EGLint)config_size,
+        (EGLint *)num_config
+    );
+
+exit:
+    if (num_config_base) {
+        _env->ReleasePrimitiveArrayCritical(num_config_ref, num_config_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (configs) {
+        for (int i = 0; i < _configsRemaining; i++) {
+            jobject configs_new = toEGLHandle(_env, eglconfigClass, eglconfigConstructor, configs[i]);
+            _env->SetObjectArrayElement(configs_ref, i + configsOffset, configs_new);
+        }
+        delete[] configs;
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglGetConfigAttrib ( EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value ) */
+static jboolean
+android_eglGetConfigAttrib
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jint attribute, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    EGLint *value_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *value = (EGLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
+        goto exit;
+    }
+    value_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglGetConfigAttrib(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLint)attribute,
+        (EGLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateWindowSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject win, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = "";
+    const char * _exceptionMessage = "";
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    int attrib_list_sentinel = 0;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    android::sp<ANativeWindow> window;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    if (win == NULL) {
+not_valid_surface:
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface";
+        goto exit;
+    }
+
+    window = android::android_Surface_getNativeWindow(_env, win);
+
+    if (window == NULL)
+        goto not_valid_surface;
+
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = 0;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+            attrib_list_sentinel = 1;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLNativeWindowType)window.get(),
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateWindowSurfaceTexture
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject win, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = "";
+    const char * _exceptionMessage = "";
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    int attrib_list_sentinel = 0;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    android::sp<ANativeWindow> window;
+    android::sp<android::SurfaceTexture> surfaceTexture;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    if (win == NULL) {
+not_valid_surface:
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface";
+        goto exit;
+    }
+    surfaceTexture = android::SurfaceTexture_getSurfaceTexture(_env, win);
+    window = new android::SurfaceTextureClient(surfaceTexture);
+
+    if (window == NULL)
+        goto not_valid_surface;
+
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = 0;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+            attrib_list_sentinel = 1;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLNativeWindowType)window.get(),
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+/* EGLSurface eglCreatePbufferSurface ( EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePbufferSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = false;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreatePbufferSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreatePixmapSurface ( EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePixmapSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jint pixmap, jintArray attrib_list_ref, jint offset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
+        "eglCreatePixmapSurface");
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0);
+}
+
+/* EGLBoolean eglDestroySurface ( EGLDisplay dpy, EGLSurface surface ) */
+static jboolean
+android_eglDestroySurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglDestroySurface(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglQuerySurface ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value ) */
+static jboolean
+android_eglQuerySurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint attribute, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+    EGLint *value_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *value = (EGLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
+        goto exit;
+    }
+    value_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglQuerySurface(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)attribute,
+        (EGLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglBindAPI ( EGLenum api ) */
+static jboolean
+android_eglBindAPI
+  (JNIEnv *_env, jobject _this, jint api) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglBindAPI(
+        (EGLenum)api
+    );
+    return _returnValue;
+}
+
+/* EGLenum eglQueryAPI ( void ) */
+static jint
+android_eglQueryAPI
+  (JNIEnv *_env, jobject _this) {
+    EGLenum _returnValue = (EGLenum) 0;
+    _returnValue = eglQueryAPI();
+    return _returnValue;
+}
+
+/* EGLBoolean eglWaitClient ( void ) */
+static jboolean
+android_eglWaitClient
+  (JNIEnv *_env, jobject _this) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglWaitClient();
+    return _returnValue;
+}
+
+/* EGLBoolean eglReleaseThread ( void ) */
+static jboolean
+android_eglReleaseThread
+  (JNIEnv *_env, jobject _this) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglReleaseThread();
+    return _returnValue;
+}
+
+/* EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePbufferFromClientBuffer
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = false;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreatePbufferFromClientBuffer(
+        (EGLDisplay)dpy_native,
+        (EGLenum)buftype,
+        (EGLClientBuffer)buffer,
+        (EGLConfig)config_native,
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value ) */
+static jboolean
+android_eglSurfaceAttrib
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint attribute, jint value) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglSurfaceAttrib(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)attribute,
+        (EGLint)value
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglBindTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer ) */
+static jboolean
+android_eglBindTexImage
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint buffer) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglBindTexImage(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)buffer
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglReleaseTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer ) */
+static jboolean
+android_eglReleaseTexImage
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint buffer) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglReleaseTexImage(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)buffer
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglSwapInterval ( EGLDisplay dpy, EGLint interval ) */
+static jboolean
+android_eglSwapInterval
+  (JNIEnv *_env, jobject _this, jobject dpy, jint interval) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+
+    _returnValue = eglSwapInterval(
+        (EGLDisplay)dpy_native,
+        (EGLint)interval
+    );
+    return _returnValue;
+}
+
+/* EGLContext eglCreateContext ( EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateContext
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject share_context, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLContext _returnValue = (EGLContext) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    EGLContext share_context_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, share_context);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = false;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateContext(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLContext)share_context_native,
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglcontextClass, eglcontextConstructor, _returnValue);
+}
+
+/* EGLBoolean eglDestroyContext ( EGLDisplay dpy, EGLContext ctx ) */
+static jboolean
+android_eglDestroyContext
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject ctx) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLContext ctx_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, ctx);
+
+    _returnValue = eglDestroyContext(
+        (EGLDisplay)dpy_native,
+        (EGLContext)ctx_native
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglMakeCurrent ( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx ) */
+static jboolean
+android_eglMakeCurrent
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject draw, jobject read, jobject ctx) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface draw_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, draw);
+    EGLSurface read_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, read);
+    EGLContext ctx_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, ctx);
+
+    _returnValue = eglMakeCurrent(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)draw_native,
+        (EGLSurface)read_native,
+        (EGLContext)ctx_native
+    );
+    return _returnValue;
+}
+
+/* EGLContext eglGetCurrentContext ( void ) */
+static jobject
+android_eglGetCurrentContext
+  (JNIEnv *_env, jobject _this) {
+    EGLContext _returnValue = (EGLContext) 0;
+    _returnValue = eglGetCurrentContext();
+    return toEGLHandle(_env, eglcontextClass, eglcontextConstructor, _returnValue);
+}
+
+/* EGLSurface eglGetCurrentSurface ( EGLint readdraw ) */
+static jobject
+android_eglGetCurrentSurface
+  (JNIEnv *_env, jobject _this, jint readdraw) {
+    EGLSurface _returnValue = (EGLSurface) 0;
+    _returnValue = eglGetCurrentSurface(
+        (EGLint)readdraw
+    );
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLDisplay eglGetCurrentDisplay ( void ) */
+static jobject
+android_eglGetCurrentDisplay
+  (JNIEnv *_env, jobject _this) {
+    EGLDisplay _returnValue = (EGLDisplay) 0;
+    _returnValue = eglGetCurrentDisplay();
+    return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
+}
+
+/* EGLBoolean eglQueryContext ( EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value ) */
+static jboolean
+android_eglQueryContext
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject ctx, jint attribute, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLContext ctx_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, ctx);
+    EGLint *value_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *value = (EGLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
+        goto exit;
+    }
+    value_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglQueryContext(
+        (EGLDisplay)dpy_native,
+        (EGLContext)ctx_native,
+        (EGLint)attribute,
+        (EGLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglWaitGL ( void ) */
+static jboolean
+android_eglWaitGL
+  (JNIEnv *_env, jobject _this) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglWaitGL();
+    return _returnValue;
+}
+
+/* EGLBoolean eglWaitNative ( EGLint engine ) */
+static jboolean
+android_eglWaitNative
+  (JNIEnv *_env, jobject _this, jint engine) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglWaitNative(
+        (EGLint)engine
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface ) */
+static jboolean
+android_eglSwapBuffers
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglSwapBuffers(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target ) */
+static jboolean
+android_eglCopyBuffers
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint target) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
+        "eglCopyBuffers");
+    return (EGLBoolean) 0;
+}
+
+static const char *classPathName = "android/opengl/EGL14";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"eglGetError", "()I", (void *) android_eglGetError },
+{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
+{"eglInitialize", "(Landroid/opengl/EGLDisplay;[II[II)Z", (void *) android_eglInitialize },
+{"eglTerminate", "(Landroid/opengl/EGLDisplay;)Z", (void *) android_eglTerminate },
+{"eglQueryString", "(Landroid/opengl/EGLDisplay;I)Ljava/lang/String;", (void *) android_eglQueryString__Landroind_opengl_EGLDisplay_2I },
+{"eglGetConfigs", "(Landroid/opengl/EGLDisplay;[Landroid/opengl/EGLConfig;II[II)Z", (void *) android_eglGetConfigs },
+{"eglChooseConfig", "(Landroid/opengl/EGLDisplay;[II[Landroid/opengl/EGLConfig;II[II)Z", (void *) android_eglChooseConfig },
+{"eglGetConfigAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;I[II)Z", (void *) android_eglGetConfigAttrib },
+{"_eglCreateWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/lang/Object;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/lang/Object;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreateWindowSurfaceTexture },
+{"eglCreatePbufferSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferSurface },
+{"eglCreatePixmapSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;I[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePixmapSurface },
+{"eglDestroySurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;)Z", (void *) android_eglDestroySurface },
+{"eglQuerySurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I[II)Z", (void *) android_eglQuerySurface },
+{"eglBindAPI", "(I)Z", (void *) android_eglBindAPI },
+{"eglQueryAPI", "()I", (void *) android_eglQueryAPI },
+{"eglWaitClient", "()Z", (void *) android_eglWaitClient },
+{"eglReleaseThread", "()Z", (void *) android_eglReleaseThread },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
+{"eglSurfaceAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;II)Z", (void *) android_eglSurfaceAttrib },
+{"eglBindTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglBindTexImage },
+{"eglReleaseTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglReleaseTexImage },
+{"eglSwapInterval", "(Landroid/opengl/EGLDisplay;I)Z", (void *) android_eglSwapInterval },
+{"eglCreateContext", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Landroid/opengl/EGLContext;[II)Landroid/opengl/EGLContext;", (void *) android_eglCreateContext },
+{"eglDestroyContext", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;)Z", (void *) android_eglDestroyContext },
+{"eglMakeCurrent", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;Landroid/opengl/EGLSurface;Landroid/opengl/EGLContext;)Z", (void *) android_eglMakeCurrent },
+{"eglGetCurrentContext", "()Landroid/opengl/EGLContext;", (void *) android_eglGetCurrentContext },
+{"eglGetCurrentSurface", "(I)Landroid/opengl/EGLSurface;", (void *) android_eglGetCurrentSurface },
+{"eglGetCurrentDisplay", "()Landroid/opengl/EGLDisplay;", (void *) android_eglGetCurrentDisplay },
+{"eglQueryContext", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;I[II)Z", (void *) android_eglQueryContext },
+{"eglWaitGL", "()Z", (void *) android_eglWaitGL },
+{"eglWaitNative", "(I)Z", (void *) android_eglWaitNative },
+{"eglSwapBuffers", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;)Z", (void *) android_eglSwapBuffers },
+{"eglCopyBuffers", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglCopyBuffers },
+};
+
+int register_android_opengl_jni_EGL14(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 6c29d6c..571f579 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -75,14 +75,12 @@
 }
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -97,11 +95,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 static void
@@ -292,6 +289,7 @@
 android_glColorPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -315,10 +313,15 @@
 android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexImage2D(
         (GLenum)target,
         (GLint)level,
@@ -339,10 +342,15 @@
 android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexSubImage2D(
         (GLenum)target,
         (GLint)level,
@@ -404,21 +412,30 @@
 static void
 android_glDeleteTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -435,21 +452,34 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
 static void
 android_glDeleteTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glDeleteTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -459,6 +489,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDepthFunc ( GLenum func ) */
@@ -532,15 +565,25 @@
 static void
 android_glDrawElements__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *indices = (GLvoid *) 0;
 
-    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < count) {
-        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count < needed";
         goto exit;
     }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (GLvoid *) (_indicesBase + _bufferOffset);
+    }
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
@@ -552,6 +595,9 @@
     if (_array) {
         releasePointer(_env, _array, indices, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEnable ( GLenum cap ) */
@@ -600,16 +646,23 @@
 static void
 android_glFogfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -639,7 +692,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -656,17 +711,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glFogfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -693,9 +755,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glFogfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -705,6 +773,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogx ( GLenum pname, GLfixed param ) */
@@ -721,16 +792,23 @@
 static void
 android_glFogxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -760,7 +838,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -777,17 +857,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glFogxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -814,9 +901,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glFogxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -826,6 +919,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFrontFace ( GLenum mode ) */
@@ -870,24 +966,29 @@
 android_glGenTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -904,6 +1005,9 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenTextures ( GLsizei n, GLuint *textures ) */
@@ -911,16 +1015,24 @@
 android_glGenTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glGenTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -930,6 +1042,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glGetError ( void ) */
@@ -946,18 +1061,22 @@
 android_glGetIntegerv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1294,7 +1413,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1311,6 +1431,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetIntegerv ( GLenum pname, GLint *params ) */
@@ -1318,11 +1441,14 @@
 android_glGetIntegerv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_ALPHA_BITS)
@@ -1656,9 +1782,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetIntegerv(
         (GLenum)pname,
         (GLint *)params
@@ -1668,6 +1799,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* const GLubyte * glGetString ( GLenum name ) */
@@ -1699,16 +1833,23 @@
 static void
 android_glLightModelfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1729,7 +1870,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1746,17 +1889,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glLightModelfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -1774,9 +1924,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightModelfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -1786,6 +1942,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelx ( GLenum pname, GLfixed param ) */
@@ -1802,16 +1961,23 @@
 static void
 android_glLightModelxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1832,7 +1998,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1849,17 +2017,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glLightModelxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -1877,9 +2052,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightModelxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -1889,6 +2070,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightf ( GLenum light, GLenum pname, GLfloat param ) */
@@ -1906,16 +2090,23 @@
 static void
 android_glLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1962,7 +2153,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1980,17 +2173,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) */
 static void
 android_glLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2034,9 +2234,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -2047,6 +2253,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightx ( GLenum light, GLenum pname, GLfixed param ) */
@@ -2064,16 +2273,23 @@
 static void
 android_glLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2120,7 +2336,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2138,17 +2356,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) */
 static void
 android_glLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2192,9 +2417,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -2205,6 +2436,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLineWidth ( GLfloat width ) */
@@ -2236,16 +2470,23 @@
 static void
 android_glLoadMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2262,6 +2503,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixf ( const GLfloat *m ) */
@@ -2269,10 +2513,15 @@
 android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixf(
         (GLfloat *)m
     );
@@ -2285,16 +2534,23 @@
 static void
 android_glLoadMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2311,6 +2567,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2318,10 +2577,15 @@
 android_glLoadMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixx(
         (GLfixed *)m
     );
@@ -2354,16 +2618,23 @@
 static void
 android_glMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2396,7 +2667,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2414,17 +2687,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) */
 static void
 android_glMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2454,9 +2734,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -2467,6 +2753,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialx ( GLenum face, GLenum pname, GLfixed param ) */
@@ -2484,16 +2773,23 @@
 static void
 android_glMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2526,7 +2822,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2544,17 +2842,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) */
 static void
 android_glMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2584,9 +2889,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -2597,6 +2908,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMatrixMode ( GLenum mode ) */
@@ -2612,16 +2926,23 @@
 static void
 android_glMultMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2638,6 +2959,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixf ( const GLfloat *m ) */
@@ -2645,10 +2969,15 @@
 android_glMultMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glMultMatrixf(
         (GLfloat *)m
     );
@@ -2661,16 +2990,23 @@
 static void
 android_glMultMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2687,6 +3023,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixx ( const GLfixed *m ) */
@@ -2694,10 +3033,15 @@
 android_glMultMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glMultMatrixx(
         (GLfixed *)m
     );
@@ -2759,6 +3103,7 @@
 android_glNormalPointerBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2870,12 +3215,16 @@
 static void
 android_glReadPixels__IIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
-    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    if (pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
+    }
     glReadPixels(
         (GLint)x,
         (GLint)y,
@@ -2886,7 +3235,7 @@
         (GLvoid *)pixels
     );
     if (_array) {
-        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, pixels, JNI_TRUE);
     }
 }
 
@@ -3013,6 +3362,7 @@
 android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -3046,16 +3396,23 @@
 static void
 android_glTexEnvfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3082,7 +3439,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3100,17 +3459,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexEnvfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3134,9 +3500,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvfv(
         (GLenum)target,
         (GLenum)pname,
@@ -3147,6 +3519,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvx ( GLenum target, GLenum pname, GLfixed param ) */
@@ -3164,16 +3539,23 @@
 static void
 android_glTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3200,7 +3582,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -3218,17 +3602,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3252,9 +3643,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvxv(
         (GLenum)target,
         (GLenum)pname,
@@ -3265,6 +3662,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) */
@@ -3272,11 +3672,16 @@
 android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexImage2D(
         (GLenum)target,
@@ -3321,11 +3726,16 @@
 android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexSubImage2D(
         (GLenum)target,
@@ -3370,6 +3780,7 @@
 android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 1154cef..1cd8e44 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -63,14 +63,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -85,11 +83,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -106,6 +103,8 @@
 android_glQueryMatrixxOES___3II_3II
   (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLbitfield _returnValue = -1;
     GLfixed *mantissa_base = (GLfixed *) 0;
     jint _mantissaRemaining;
@@ -116,18 +115,21 @@
 
     if (!mantissa_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissa == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissa == null";
         goto exit;
     }
     if (mantissaOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissaOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissaOffset < 0";
         goto exit;
     }
     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - mantissaOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - mantissaOffset < 16 < needed";
         goto exit;
     }
     mantissa_base = (GLfixed *)
@@ -136,18 +138,21 @@
 
     if (!exponent_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponent == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponent == null";
         goto exit;
     }
     if (exponentOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponentOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponentOffset < 0";
         goto exit;
     }
     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - exponentOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - exponentOffset < 16 < needed";
         goto exit;
     }
     exponent_base = (GLint *)
@@ -168,6 +173,9 @@
         _env->ReleasePrimitiveArrayCritical(mantissa_ref, mantissa_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -176,37 +184,54 @@
 android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _mantissaArray = (jarray) 0;
+    jint _mantissaBufferOffset = (jint) 0;
     jarray _exponentArray = (jarray) 0;
+    jint _exponentBufferOffset = (jint) 0;
     GLbitfield _returnValue = -1;
     jint _mantissaRemaining;
     GLfixed *mantissa = (GLfixed *) 0;
     jint _exponentRemaining;
     GLint *exponent = (GLint *) 0;
 
-    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
+    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
-    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
+    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
+    if (mantissa == NULL) {
+        char * _mantissaBase = (char *)_env->GetPrimitiveArrayCritical(_mantissaArray, (jboolean *) 0);
+        mantissa = (GLfixed *) (_mantissaBase + _mantissaBufferOffset);
+    }
+    if (exponent == NULL) {
+        char * _exponentBase = (char *)_env->GetPrimitiveArrayCritical(_exponentArray, (jboolean *) 0);
+        exponent = (GLint *) (_exponentBase + _exponentBufferOffset);
+    }
     _returnValue = glQueryMatrixxOES(
         (GLfixed *)mantissa,
         (GLint *)exponent
     );
 
 exit:
-    if (_mantissaArray) {
-        releasePointer(_env, _mantissaArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_exponentArray) {
-        releasePointer(_env, _exponentArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _exponentArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_mantissaArray) {
+        releasePointer(_env, _mantissaArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
     }
     return _returnValue;
 }
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index d038f20..1e6ceb3 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -70,14 +70,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -92,11 +90,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -136,17 +133,27 @@
 static void
 android_glBufferData__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
     if (data_buf) {
-        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
         if (_remaining < size) {
-            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "remaining() < size < needed";
             goto exit;
         }
     }
+    if (data_buf && data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferData(
         (GLenum)target,
         (GLsizeiptr)size,
@@ -158,21 +165,34 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
 static void
 android_glBufferSubData__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < size) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < size < needed";
         goto exit;
     }
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferSubData(
         (GLenum)target,
         (GLintptr)offset,
@@ -184,22 +204,32 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *equation_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -217,17 +247,28 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
-    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfloat *) (_equationBase + _bufferOffset);
+    }
     glClipPlanef(
         (GLenum)plane,
         (GLfloat *)equation
@@ -235,22 +276,32 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *equation_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -268,17 +319,28 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
-    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfixed *) (_equationBase + _bufferOffset);
+    }
     glClipPlanex(
         (GLenum)plane,
         (GLfixed *)equation
@@ -286,6 +348,9 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) */
@@ -316,21 +381,30 @@
 static void
 android_glDeleteBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -347,21 +421,34 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
 static void
 android_glDeleteBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glDeleteBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -371,18 +458,27 @@
     if (_array) {
         releasePointer(_env, _array, buffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset ) */
 static void
 android_glDrawElements__IIII
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
         (const GLvoid *)offset
     );
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -390,24 +486,29 @@
 android_glGenBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -424,6 +525,9 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -431,16 +535,24 @@
 android_glGenBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glGenBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -450,6 +562,9 @@
     if (_array) {
         releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
@@ -457,18 +572,22 @@
 android_glGetBooleanv__I_3ZI
   (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLboolean *params_base = (GLboolean *) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -486,24 +605,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
 static void
 android_glGetBooleanv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
-    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLboolean *) (_paramsBase + _bufferOffset);
+    }
     glGetBooleanv(
         (GLenum)pname,
         (GLboolean *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -512,24 +638,29 @@
 android_glGetBufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -547,6 +678,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -554,16 +688,24 @@
 android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetBufferParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -574,6 +716,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
@@ -581,18 +726,22 @@
 android_glGetClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *eqn_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -610,24 +759,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
 static void
 android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
-    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfloat *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanef(
         (GLenum)pname,
         (GLfloat *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -636,18 +792,22 @@
 android_glGetClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *eqn_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -665,24 +825,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) */
 static void
 android_glGetClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
-    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfixed *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanex(
         (GLenum)pname,
         (GLfixed *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -691,18 +858,22 @@
 android_glGetFixedv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -720,24 +891,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedv ( GLenum pname, GLfixed *params ) */
 static void
 android_glGetFixedv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetFixedv(
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -746,18 +924,22 @@
 android_glGetFloatv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -775,24 +957,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFloatv ( GLenum pname, GLfloat *params ) */
 static void
 android_glGetFloatv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetFloatv(
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -801,18 +990,22 @@
 android_glGetLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -860,7 +1053,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -878,6 +1072,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) */
@@ -885,11 +1082,14 @@
 android_glGetLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -934,9 +1134,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -947,6 +1152,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -954,18 +1162,22 @@
 android_glGetLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1013,7 +1225,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1031,6 +1244,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -1038,11 +1254,14 @@
 android_glGetLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -1087,9 +1306,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -1100,6 +1324,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -1107,18 +1334,22 @@
 android_glGetMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1152,7 +1383,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1170,6 +1402,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -1177,11 +1412,14 @@
 android_glGetMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -1212,9 +1450,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -1225,6 +1468,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -1232,18 +1478,22 @@
 android_glGetMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1277,7 +1527,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1295,6 +1546,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -1302,11 +1556,14 @@
 android_glGetMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -1337,9 +1594,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -1350,6 +1612,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params ) */
@@ -1357,18 +1622,22 @@
 android_glGetTexEnvfv__II_3FI
   (JNIEnv *_env, jobject _this, jint env, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1396,7 +1665,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1414,6 +1684,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params ) */
@@ -1421,11 +1694,14 @@
 android_glGetTexEnvfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -1450,9 +1726,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvfv(
         (GLenum)env,
         (GLenum)pname,
@@ -1463,6 +1744,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -1470,18 +1754,22 @@
 android_glGetTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1509,7 +1797,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1527,6 +1816,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -1534,11 +1826,14 @@
 android_glGetTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -1563,9 +1858,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnviv(
         (GLenum)env,
         (GLenum)pname,
@@ -1576,6 +1876,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -1583,18 +1886,22 @@
 android_glGetTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1622,7 +1929,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1640,6 +1948,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -1647,11 +1958,14 @@
 android_glGetTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -1676,9 +1990,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvxv(
         (GLenum)env,
         (GLenum)pname,
@@ -1689,6 +2008,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -1696,24 +2018,29 @@
 android_glGetTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1731,6 +2058,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -1738,16 +2068,24 @@
 android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -1758,6 +2096,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1765,24 +2106,29 @@
 android_glGetTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1800,6 +2146,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1807,16 +2156,24 @@
 android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -1827,6 +2184,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -1834,24 +2194,29 @@
 android_glGetTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1869,6 +2234,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -1876,16 +2244,24 @@
 android_glGetTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -1896,6 +2272,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLboolean glIsBuffer ( GLuint buffer ) */
@@ -1956,21 +2335,30 @@
 static void
 android_glPointParameterfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1987,21 +2375,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glPointParameterfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -2011,6 +2412,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterx ( GLenum pname, GLfixed param ) */
@@ -2027,21 +2431,30 @@
 static void
 android_glPointParameterxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2058,21 +2471,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glPointParameterxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -2082,6 +2508,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer ) */
@@ -2089,6 +2518,7 @@
 android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2133,16 +2563,23 @@
 static void
 android_glTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2169,7 +2606,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2187,17 +2626,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -2221,9 +2667,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexEnviv(
         (GLenum)target,
         (GLenum)pname,
@@ -2234,27 +2686,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2272,21 +2736,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -2297,6 +2774,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
@@ -2314,21 +2794,30 @@
 static void
 android_glTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2346,21 +2835,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -2371,27 +2873,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2409,21 +2923,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -2434,6 +2961,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index d6dc0fe..073bbb2 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -72,14 +72,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -94,11 +92,9 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -197,21 +193,30 @@
 static void
 android_glDrawTexsvOES___3SI
   (JNIEnv *_env, jobject _this, jshortArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLshort *coords_base = (GLshort *) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLshort *)
@@ -227,21 +232,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexsvOES ( const GLshort *coords ) */
 static void
 android_glDrawTexsvOES__Ljava_nio_ShortBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
-    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLshort *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexsvOES(
         (GLshort *)coords
     );
@@ -250,27 +268,39 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexivOES ( const GLint *coords ) */
 static void
 android_glDrawTexivOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *coords_base = (GLint *) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLint *)
@@ -286,21 +316,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexivOES ( const GLint *coords ) */
 static void
 android_glDrawTexivOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
-    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLint *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexivOES(
         (GLint *)coords
     );
@@ -309,27 +352,39 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxvOES ( const GLfixed *coords ) */
 static void
 android_glDrawTexxvOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *coords_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfixed *)
@@ -345,21 +400,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxvOES ( const GLfixed *coords ) */
 static void
 android_glDrawTexxvOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
-    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfixed *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexxvOES(
         (GLfixed *)coords
     );
@@ -368,6 +436,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height ) */
@@ -387,21 +458,30 @@
 static void
 android_glDrawTexfvOES___3FI
   (JNIEnv *_env, jobject _this, jfloatArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *coords_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfloat *)
@@ -417,21 +497,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexfvOES ( const GLfloat *coords ) */
 static void
 android_glDrawTexfvOES__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
-    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfloat *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexfvOES(
         (GLfloat *)coords
     );
@@ -440,24 +533,31 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEGLImageTargetTexture2DOES ( GLenum target, GLeglImageOES image ) */
 static void
 android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLeglImageOES image = (GLeglImageOES) 0;
 
-    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining);
+    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining, &_bufferOffset);
+    if (image == NULL) {
+        char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        image = (GLeglImageOES) (_imageBase + _bufferOffset);
+    }
     glEGLImageTargetTexture2DOES(
         (GLenum)target,
         (GLeglImageOES)image
     );
     if (_array) {
-        releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, image, JNI_TRUE);
     }
 }
 
@@ -465,18 +565,22 @@
 static void
 android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLeglImageOES image = (GLeglImageOES) 0;
 
-    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining);
+    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining, &_bufferOffset);
+    if (image == NULL) {
+        char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        image = (GLeglImageOES) (_imageBase + _bufferOffset);
+    }
     glEGLImageTargetRenderbufferStorageOES(
         (GLenum)target,
         (GLeglImageOES)image
     );
     if (_array) {
-        releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, image, JNI_TRUE);
     }
 }
 
@@ -515,16 +619,23 @@
 static void
 android_glClipPlanexOES__I_3II
   (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *equation_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -542,6 +653,9 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanexOES ( GLenum plane, const GLfixed *equation ) */
@@ -549,10 +663,15 @@
 android_glClipPlanexOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
-    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfixed *) (_equationBase + _bufferOffset);
+    }
     glClipPlanexOES(
         (GLenum)plane,
         (GLfixed *)equation
@@ -598,16 +717,23 @@
 static void
 android_glFogxvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -625,6 +751,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogxvOES ( GLenum pname, const GLfixed *params ) */
@@ -632,10 +761,15 @@
 android_glFogxvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glFogxvOES(
         (GLenum)pname,
         (GLfixed *)params
@@ -664,24 +798,29 @@
 android_glGetClipPlanexOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *eqn_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     eqn_base = (GLfixed *)
@@ -698,6 +837,9 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn ) */
@@ -705,16 +847,24 @@
 android_glGetClipPlanexOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
-    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfixed *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanexOES(
         (GLenum)pname,
         (GLfixed *)eqn
@@ -724,6 +874,9 @@
     if (_array) {
         releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */
@@ -731,18 +884,22 @@
 android_glGetFixedvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -760,24 +917,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */
 static void
 android_glGetFixedvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetFixedvOES(
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -786,18 +950,22 @@
 android_glGetLightxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -816,25 +984,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params ) */
 static void
 android_glGetLightxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetLightxvOES(
         (GLenum)light,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -843,18 +1018,22 @@
 android_glGetMaterialxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -873,25 +1052,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params ) */
 static void
 android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialxvOES(
         (GLenum)face,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -900,18 +1086,22 @@
 android_glGetTexEnvxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -930,25 +1120,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params ) */
 static void
 android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvxvOES(
         (GLenum)env,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -957,18 +1154,22 @@
 android_glGetTexParameterxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -987,25 +1188,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params ) */
 static void
 android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterxvOES(
         (GLenum)target,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1023,16 +1231,23 @@
 static void
 android_glLightModelxvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1050,6 +1265,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelxvOES ( GLenum pname, const GLfixed *params ) */
@@ -1057,10 +1275,15 @@
 android_glLightModelxvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightModelxvOES(
         (GLenum)pname,
         (GLfixed *)params
@@ -1085,16 +1308,23 @@
 static void
 android_glLightxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1113,6 +1343,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params ) */
@@ -1120,10 +1353,15 @@
 android_glLightxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightxvOES(
         (GLenum)light,
         (GLenum)pname,
@@ -1147,16 +1385,23 @@
 static void
 android_glLoadMatrixxOES___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -1173,6 +1418,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixxOES ( const GLfixed *m ) */
@@ -1180,10 +1428,15 @@
 android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixxOES(
         (GLfixed *)m
     );
@@ -1207,16 +1460,23 @@
 static void
 android_glMaterialxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1235,6 +1495,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params ) */
@@ -1242,10 +1505,15 @@
 android_glMaterialxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glMaterialxvOES(
         (GLenum)face,
         (GLenum)pname,
@@ -1260,16 +1528,23 @@
 static void
 android_glMultMatrixxOES___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -1286,6 +1561,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixxOES ( const GLfixed *m ) */
@@ -1293,10 +1571,15 @@
 android_glMultMatrixxOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glMultMatrixxOES(
         (GLfixed *)m
     );
@@ -1357,16 +1640,23 @@
 static void
 android_glPointParameterxvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1384,6 +1674,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterxvOES ( GLenum pname, const GLfixed *params ) */
@@ -1391,10 +1684,15 @@
 android_glPointParameterxvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterxvOES(
         (GLenum)pname,
         (GLfixed *)params
@@ -1471,16 +1769,23 @@
 static void
 android_glTexEnvxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1499,6 +1804,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
@@ -1506,10 +1814,15 @@
 android_glTexEnvxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvxvOES(
         (GLenum)target,
         (GLenum)pname,
@@ -1535,16 +1848,23 @@
 static void
 android_glTexParameterxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1563,6 +1883,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
@@ -1570,10 +1893,15 @@
 android_glTexParameterxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterxvOES(
         (GLenum)target,
         (GLenum)pname,
@@ -1620,21 +1948,30 @@
 static void
 android_glDeleteRenderbuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -1651,21 +1988,34 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers ) */
 static void
 android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glDeleteRenderbuffersOES(
         (GLsizei)n,
         (GLuint *)renderbuffers
@@ -1675,6 +2025,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
@@ -1682,24 +2035,29 @@
 android_glGenRenderbuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -1716,6 +2074,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
@@ -1723,16 +2084,24 @@
 android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glGenRenderbuffersOES(
         (GLsizei)n,
         (GLuint *)renderbuffers
@@ -1742,6 +2111,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height ) */
@@ -1761,24 +2133,29 @@
 android_glGetRenderbufferParameterivOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1796,6 +2173,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params ) */
@@ -1803,16 +2183,24 @@
 android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetRenderbufferParameterivOES(
         (GLenum)target,
         (GLenum)pname,
@@ -1823,6 +2211,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLboolean glIsFramebufferOES ( GLuint framebuffer ) */
@@ -1850,21 +2241,30 @@
 static void
 android_glDeleteFramebuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -1881,21 +2281,34 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers ) */
 static void
 android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glDeleteFramebuffersOES(
         (GLsizei)n,
         (GLuint *)framebuffers
@@ -1905,6 +2318,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
@@ -1912,24 +2328,29 @@
 android_glGenFramebuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -1946,6 +2367,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
@@ -1953,16 +2377,24 @@
 android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glGenFramebuffersOES(
         (GLsizei)n,
         (GLuint *)framebuffers
@@ -1972,6 +2404,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glCheckFramebufferStatusOES ( GLenum target ) */
@@ -2015,24 +2450,29 @@
 android_glGetFramebufferAttachmentParameterivOES__III_3II
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2051,6 +2491,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
@@ -2058,16 +2501,24 @@
 android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetFramebufferAttachmentParameterivOES(
         (GLenum)target,
         (GLenum)attachment,
@@ -2079,6 +2530,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenerateMipmapOES ( GLenum target ) */
@@ -2111,6 +2565,7 @@
 android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2134,6 +2589,7 @@
 android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2194,16 +2650,23 @@
 static void
 android_glClipPlanefOES__I_3FI
   (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *equation_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -2221,6 +2684,9 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanefOES ( GLenum plane, const GLfloat *equation ) */
@@ -2228,10 +2694,15 @@
 android_glClipPlanefOES__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
-    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfloat *) (_equationBase + _bufferOffset);
+    }
     glClipPlanefOES(
         (GLenum)plane,
         (GLfloat *)equation
@@ -2246,24 +2717,29 @@
 android_glGetClipPlanefOES__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *eqn_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     eqn_base = (GLfloat *)
@@ -2280,6 +2756,9 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */
@@ -2287,16 +2766,24 @@
 android_glGetClipPlanefOES__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
-    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfloat *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanefOES(
         (GLenum)pname,
         (GLfloat *)eqn
@@ -2306,6 +2793,9 @@
     if (_array) {
         releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClearDepthfOES ( GLclampf depth ) */
@@ -2332,16 +2822,23 @@
 static void
 android_glTexGenfvOES__II_3FI
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2360,6 +2857,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params ) */
@@ -2367,10 +2867,15 @@
 android_glTexGenfvOES__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexGenfvOES(
         (GLenum)coord,
         (GLenum)pname,
@@ -2396,16 +2901,23 @@
 static void
 android_glTexGenivOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2424,6 +2936,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params ) */
@@ -2431,10 +2946,15 @@
 android_glTexGenivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexGenivOES(
         (GLenum)coord,
         (GLenum)pname,
@@ -2460,16 +2980,23 @@
 static void
 android_glTexGenxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2488,6 +3015,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params ) */
@@ -2495,10 +3025,15 @@
 android_glTexGenxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexGenxvOES(
         (GLenum)coord,
         (GLenum)pname,
@@ -2514,18 +3049,22 @@
 android_glGetTexGenfvOES__II_3FI
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2544,25 +3083,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */
 static void
 android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenfvOES(
         (GLenum)coord,
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2571,18 +3117,22 @@
 android_glGetTexGenivOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2601,25 +3151,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params ) */
 static void
 android_glGetTexGenivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenivOES(
         (GLenum)coord,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2628,18 +3185,22 @@
 android_glGetTexGenxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2658,25 +3219,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params ) */
 static void
 android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenxvOES(
         (GLenum)coord,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index a53e4d7..c530117 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -63,14 +63,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -85,11 +83,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -150,10 +147,14 @@
 static void
 android_glBindAttribLocation__IILjava_lang_String_2
   (JNIEnv *_env, jobject _this, jint program, jint index, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     const char* _nativename = 0;
 
     if (!name) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -169,6 +170,9 @@
         _env->ReleaseStringUTFChars(name, _nativename);
     }
 
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBindBuffer ( GLenum target, GLuint buffer ) */
@@ -268,17 +272,27 @@
 static void
 android_glBufferData__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
     if (data_buf) {
-        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
         if (_remaining < size) {
-            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "remaining() < size < needed";
             goto exit;
         }
     }
+    if (data_buf && data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferData(
         (GLenum)target,
         (GLsizeiptr)size,
@@ -290,21 +304,34 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
 static void
 android_glBufferSubData__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < size) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < size < needed";
         goto exit;
     }
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferSubData(
         (GLenum)target,
         (GLintptr)offset,
@@ -316,6 +343,9 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glCheckFramebufferStatus ( GLenum target ) */
@@ -394,10 +424,15 @@
 android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexImage2D(
         (GLenum)target,
         (GLint)level,
@@ -418,10 +453,15 @@
 android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexSubImage2D(
         (GLenum)target,
         (GLint)level,
@@ -503,21 +543,30 @@
 static void
 android_glDeleteBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -534,21 +583,34 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
 static void
 android_glDeleteBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glDeleteBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -558,22 +620,32 @@
     if (_array) {
         releasePointer(_env, _array, buffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffers ( GLsizei n, const GLuint *framebuffers ) */
 static void
 android_glDeleteFramebuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
@@ -591,6 +663,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffers ( GLsizei n, const GLuint *framebuffers ) */
@@ -598,10 +673,15 @@
 android_glDeleteFramebuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glDeleteFramebuffers(
         (GLsizei)n,
         (GLuint *)framebuffers
@@ -624,16 +704,23 @@
 static void
 android_glDeleteRenderbuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
@@ -651,6 +738,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffers ( GLsizei n, const GLuint *renderbuffers ) */
@@ -658,10 +748,15 @@
 android_glDeleteRenderbuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glDeleteRenderbuffers(
         (GLsizei)n,
         (GLuint *)renderbuffers
@@ -684,21 +779,30 @@
 static void
 android_glDeleteTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -715,21 +819,34 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
 static void
 android_glDeleteTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glDeleteTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -739,6 +856,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDepthFunc ( GLenum func ) */
@@ -812,27 +932,43 @@
 static void
 android_glDrawElements__IIII
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
         (const GLvoid *)offset
     );
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ) */
 static void
 android_glDrawElements__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *indices = (GLvoid *) 0;
 
-    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < count) {
-        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count < needed";
         goto exit;
     }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (GLvoid *) (_indicesBase + _bufferOffset);
+    }
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
@@ -844,6 +980,9 @@
     if (_array) {
         releasePointer(_env, _array, indices, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEnable ( GLenum cap ) */
@@ -917,24 +1056,29 @@
 android_glGenBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -951,6 +1095,9 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -958,16 +1105,24 @@
 android_glGenBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glGenBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -977,6 +1132,9 @@
     if (_array) {
         releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenerateMipmap ( GLenum target ) */
@@ -993,18 +1151,22 @@
 android_glGenFramebuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
@@ -1022,24 +1184,31 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffers ( GLsizei n, GLuint *framebuffers ) */
 static void
 android_glGenFramebuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glGenFramebuffers(
         (GLsizei)n,
         (GLuint *)framebuffers
     );
     if (_array) {
-        releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, framebuffers, JNI_TRUE);
     }
 }
 
@@ -1048,18 +1217,22 @@
 android_glGenRenderbuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
@@ -1077,24 +1250,31 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffers ( GLsizei n, GLuint *renderbuffers ) */
 static void
 android_glGenRenderbuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glGenRenderbuffers(
         (GLsizei)n,
         (GLuint *)renderbuffers
     );
     if (_array) {
-        releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, renderbuffers, JNI_TRUE);
     }
 }
 
@@ -1103,24 +1283,29 @@
 android_glGenTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -1137,6 +1322,9 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenTextures ( GLsizei n, GLuint *textures ) */
@@ -1144,16 +1332,24 @@
 android_glGenTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glGenTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -1163,6 +1359,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
@@ -1170,6 +1369,8 @@
 android_glGetActiveAttrib__III_3II_3II_3II_3BI
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jintArray length_ref, jint lengthOffset, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset, jbyteArray name_ref, jint nameOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *length_base = (GLsizei *) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
@@ -1185,12 +1386,14 @@
 
     if (!length_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -1200,12 +1403,14 @@
 
     if (!size_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "size == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
         goto exit;
     }
     if (sizeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "sizeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
         goto exit;
     }
     _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
@@ -1215,12 +1420,14 @@
 
     if (!type_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "type == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
         goto exit;
     }
     if (typeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "typeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
         goto exit;
     }
     _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
@@ -1230,12 +1437,14 @@
 
     if (!name_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     if (nameOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "nameOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "nameOffset < 0";
         goto exit;
     }
     _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
@@ -1270,16 +1479,21 @@
         _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
 static void
 android_glGetActiveAttrib__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
-    jint _exception = 0;
     jarray _lengthArray = (jarray) 0;
+    jint _lengthBufferOffset = (jint) 0;
     jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
     jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
@@ -1287,9 +1501,21 @@
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
 
-    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining);
-    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining);
-    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining);
+    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
+    }
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
     glGetActiveAttrib(
         (GLuint)program,
         (GLuint)index,
@@ -1299,22 +1525,180 @@
         (GLenum *)type,
         (char *)name
     );
-    if (_lengthArray) {
-        releasePointer(_env, _lengthArray, type, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
     }
     if (_sizeArray) {
-        releasePointer(_env, _sizeArray, size, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
     }
-    if (_typeArray) {
-        releasePointer(_env, _typeArray, length, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_lengthArray) {
+        releasePointer(_env, _lengthArray, length, JNI_TRUE);
     }
 }
 
+/* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveAttrib1
+  (JNIEnv *_env, jobject _this, jint program, jint index, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    GLint *size_base = (GLint *) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+    GLenum *type_base = (GLenum *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+    if (!size_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
+        goto exit;
+    }
+    if (sizeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
+        goto exit;
+    }
+    _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
+    size_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+    size = size_base + sizeOffset;
+
+    if (!type_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
+        goto exit;
+    }
+    if (typeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
+        goto exit;
+    }
+    _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
+    type_base = (GLenum *)
+        _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+    type = type_base + typeOffset;
+
+    glGetActiveAttrib(
+        (GLuint)program,
+        (GLuint)index,
+        (GLsizei)len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+exit:
+    if (type_base) {
+        _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (size_base) {
+        _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception != 1) {
+        result = _env->NewStringUTF(buf);
+    }
+    if (buf) {
+        free(buf);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    if (result == 0) {
+        result = _env->NewStringUTF("");
+    }
+
+    return result;
+}
+
+/* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveAttrib2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
+    jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
+    jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
+    jint _lengthRemaining;
+    GLsizei *length = (GLsizei *) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
+    glGetActiveAttrib(
+        (GLuint)program,
+        (GLuint)index,
+        (GLsizei)len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
+    }
+    if (_sizeArray) {
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
+    }
+    result = _env->NewStringUTF(buf);
+    if (buf) {
+        free(buf);
+    }
+    return result;
+}
 /* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
 static void
 android_glGetActiveUniform__III_3II_3II_3II_3BI
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jintArray length_ref, jint lengthOffset, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset, jbyteArray name_ref, jint nameOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *length_base = (GLsizei *) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
@@ -1330,12 +1714,14 @@
 
     if (!length_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -1345,12 +1731,14 @@
 
     if (!size_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "size == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
         goto exit;
     }
     if (sizeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "sizeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
         goto exit;
     }
     _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
@@ -1360,12 +1748,14 @@
 
     if (!type_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "type == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
         goto exit;
     }
     if (typeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "typeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
         goto exit;
     }
     _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
@@ -1375,12 +1765,14 @@
 
     if (!name_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     if (nameOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "nameOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "nameOffset < 0";
         goto exit;
     }
     _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
@@ -1415,16 +1807,21 @@
         _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
 static void
 android_glGetActiveUniform__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
-    jint _exception = 0;
     jarray _lengthArray = (jarray) 0;
+    jint _lengthBufferOffset = (jint) 0;
     jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
     jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
@@ -1432,9 +1829,21 @@
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
 
-    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining);
-    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining);
-    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining);
+    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
+    }
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
     glGetActiveUniform(
         (GLuint)program,
         (GLuint)index,
@@ -1444,22 +1853,181 @@
         (GLenum *)type,
         (char *)name
     );
-    if (_lengthArray) {
-        releasePointer(_env, _lengthArray, type, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
     }
     if (_sizeArray) {
-        releasePointer(_env, _sizeArray, size, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
     }
-    if (_typeArray) {
-        releasePointer(_env, _typeArray, length, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_lengthArray) {
+        releasePointer(_env, _lengthArray, length, JNI_TRUE);
     }
 }
 
+/* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveUniform1
+  (JNIEnv *_env, jobject _this, jint program, jint index, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+
+    GLint *size_base = (GLint *) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+
+    GLenum *type_base = (GLenum *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+
+    if (!size_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
+        goto exit;
+    }
+    if (sizeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
+        goto exit;
+    }
+    _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
+    size_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+    size = size_base + sizeOffset;
+
+    if (!type_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
+        goto exit;
+    }
+    if (typeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
+        goto exit;
+    }
+    _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
+    type_base = (GLenum *)
+        _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+    type = type_base + typeOffset;
+
+    glGetActiveUniform(
+        (GLuint)program,
+        (GLuint)index,
+        (GLsizei)len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+
+exit:
+    if (type_base) {
+        _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (size_base) {
+        _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception != 1) {
+        result = _env->NewStringUTF(buf);
+    }
+    if (buf) {
+        free(buf);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    if (result == 0) {
+        result = _env->NewStringUTF("");
+    }
+    return result;
+}
+
+/* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveUniform2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
+    jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
+    jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
+    glGetActiveUniform(
+        (GLuint)program,
+        (GLuint)index,
+        len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
+    }
+    if (_sizeArray) {
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
+    }
+    result = _env->NewStringUTF(buf);
+    if (buf) {
+        free(buf);
+    }
+    return result;
+}
 /* void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders ) */
 static void
 android_glGetAttachedShaders__II_3II_3II
   (JNIEnv *_env, jobject _this, jint program, jint maxcount, jintArray count_ref, jint countOffset, jintArray shaders_ref, jint shadersOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *count_base = (GLsizei *) 0;
     jint _countRemaining;
     GLsizei *count = (GLsizei *) 0;
@@ -1469,12 +2037,14 @@
 
     if (!count_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "count == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "count == null";
         goto exit;
     }
     if (countOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "countOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "countOffset < 0";
         goto exit;
     }
     _countRemaining = _env->GetArrayLength(count_ref) - countOffset;
@@ -1484,12 +2054,14 @@
 
     if (!shaders_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "shaders == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "shaders == null";
         goto exit;
     }
     if (shadersOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "shadersOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "shadersOffset < 0";
         goto exit;
     }
     _shadersRemaining = _env->GetArrayLength(shaders_ref) - shadersOffset;
@@ -1513,33 +2085,45 @@
         _env->ReleasePrimitiveArrayCritical(count_ref, count_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders ) */
 static void
 android_glGetAttachedShaders__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint maxcount, jobject count_buf, jobject shaders_buf) {
-    jint _exception = 0;
     jarray _countArray = (jarray) 0;
+    jint _countBufferOffset = (jint) 0;
     jarray _shadersArray = (jarray) 0;
+    jint _shadersBufferOffset = (jint) 0;
     jint _countRemaining;
     GLsizei *count = (GLsizei *) 0;
     jint _shadersRemaining;
     GLuint *shaders = (GLuint *) 0;
 
-    count = (GLsizei *)getPointer(_env, count_buf, &_countArray, &_countRemaining);
-    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining);
+    count = (GLsizei *)getPointer(_env, count_buf, &_countArray, &_countRemaining, &_countBufferOffset);
+    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+    if (count == NULL) {
+        char * _countBase = (char *)_env->GetPrimitiveArrayCritical(_countArray, (jboolean *) 0);
+        count = (GLsizei *) (_countBase + _countBufferOffset);
+    }
+    if (shaders == NULL) {
+        char * _shadersBase = (char *)_env->GetPrimitiveArrayCritical(_shadersArray, (jboolean *) 0);
+        shaders = (GLuint *) (_shadersBase + _shadersBufferOffset);
+    }
     glGetAttachedShaders(
         (GLuint)program,
         (GLsizei)maxcount,
         (GLsizei *)count,
         (GLuint *)shaders
     );
-    if (_countArray) {
-        releasePointer(_env, _countArray, shaders, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_shadersArray) {
-        releasePointer(_env, _shadersArray, count, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _shadersArray, shaders, JNI_TRUE);
+    }
+    if (_countArray) {
+        releasePointer(_env, _countArray, count, JNI_TRUE);
     }
 }
 
@@ -1547,11 +2131,15 @@
 static jint
 android_glGetAttribLocation__ILjava_lang_String_2
   (JNIEnv *_env, jobject _this, jint program, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     int _returnValue = 0;
     const char* _nativename = 0;
 
     if (!name) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -1566,6 +2154,9 @@
         _env->ReleaseStringUTFChars(name, _nativename);
     }
 
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -1574,18 +2165,22 @@
 android_glGetBooleanv__I_3ZI
   (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLboolean *params_base = (GLboolean *) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1603,24 +2198,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
 static void
 android_glGetBooleanv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
-    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLboolean *) (_paramsBase + _bufferOffset);
+    }
     glGetBooleanv(
         (GLenum)pname,
         (GLboolean *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1629,24 +2231,29 @@
 android_glGetBufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1664,6 +2271,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1671,16 +2281,24 @@
 android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetBufferParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -1691,6 +2309,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glGetError ( void ) */
@@ -1707,18 +2328,22 @@
 android_glGetFloatv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1736,24 +2361,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFloatv ( GLenum pname, GLfloat *params ) */
 static void
 android_glGetFloatv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetFloatv(
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1762,18 +2394,22 @@
 android_glGetFramebufferAttachmentParameteriv__III_3II
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1793,18 +2429,25 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameteriv ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
 static void
 android_glGetFramebufferAttachmentParameteriv__IIILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetFramebufferAttachmentParameteriv(
         (GLenum)target,
         (GLenum)attachment,
@@ -1812,7 +2455,7 @@
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1821,18 +2464,22 @@
 android_glGetIntegerv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2169,7 +2816,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2186,6 +2834,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetIntegerv ( GLenum pname, GLint *params ) */
@@ -2193,11 +2844,14 @@
 android_glGetIntegerv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_ALPHA_BITS)
@@ -2531,9 +3185,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetIntegerv(
         (GLenum)pname,
         (GLint *)params
@@ -2543,6 +3202,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetProgramiv ( GLuint program, GLenum pname, GLint *params ) */
@@ -2550,18 +3212,22 @@
 android_glGetProgramiv__II_3II
   (JNIEnv *_env, jobject _this, jint program, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2580,25 +3246,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetProgramiv ( GLuint program, GLenum pname, GLint *params ) */
 static void
 android_glGetProgramiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetProgramiv(
         (GLuint)program,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2626,18 +3299,22 @@
 android_glGetRenderbufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2656,25 +3333,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetRenderbufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
 static void
 android_glGetRenderbufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetRenderbufferParameteriv(
         (GLenum)target,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2683,18 +3367,22 @@
 android_glGetShaderiv__II_3II
   (JNIEnv *_env, jobject _this, jint shader, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2713,25 +3401,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetShaderiv ( GLuint shader, GLenum pname, GLint *params ) */
 static void
 android_glGetShaderiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint shader, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetShaderiv(
         (GLuint)shader,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2759,6 +3454,8 @@
 android_glGetShaderPrecisionFormat__II_3II_3II
   (JNIEnv *_env, jobject _this, jint shadertype, jint precisiontype, jintArray range_ref, jint rangeOffset, jintArray precision_ref, jint precisionOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *range_base = (GLint *) 0;
     jint _rangeRemaining;
     GLint *range = (GLint *) 0;
@@ -2768,12 +3465,14 @@
 
     if (!range_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "range == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "range == null";
         goto exit;
     }
     if (rangeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "rangeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "rangeOffset < 0";
         goto exit;
     }
     _rangeRemaining = _env->GetArrayLength(range_ref) - rangeOffset;
@@ -2783,12 +3482,14 @@
 
     if (!precision_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "precision == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "precision == null";
         goto exit;
     }
     if (precisionOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "precisionOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "precisionOffset < 0";
         goto exit;
     }
     _precisionRemaining = _env->GetArrayLength(precision_ref) - precisionOffset;
@@ -2812,33 +3513,45 @@
         _env->ReleasePrimitiveArrayCritical(range_ref, range_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetShaderPrecisionFormat ( GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision ) */
 static void
 android_glGetShaderPrecisionFormat__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint shadertype, jint precisiontype, jobject range_buf, jobject precision_buf) {
-    jint _exception = 0;
     jarray _rangeArray = (jarray) 0;
+    jint _rangeBufferOffset = (jint) 0;
     jarray _precisionArray = (jarray) 0;
+    jint _precisionBufferOffset = (jint) 0;
     jint _rangeRemaining;
     GLint *range = (GLint *) 0;
     jint _precisionRemaining;
     GLint *precision = (GLint *) 0;
 
-    range = (GLint *)getPointer(_env, range_buf, &_rangeArray, &_rangeRemaining);
-    precision = (GLint *)getPointer(_env, precision_buf, &_precisionArray, &_precisionRemaining);
+    range = (GLint *)getPointer(_env, range_buf, &_rangeArray, &_rangeRemaining, &_rangeBufferOffset);
+    precision = (GLint *)getPointer(_env, precision_buf, &_precisionArray, &_precisionRemaining, &_precisionBufferOffset);
+    if (range == NULL) {
+        char * _rangeBase = (char *)_env->GetPrimitiveArrayCritical(_rangeArray, (jboolean *) 0);
+        range = (GLint *) (_rangeBase + _rangeBufferOffset);
+    }
+    if (precision == NULL) {
+        char * _precisionBase = (char *)_env->GetPrimitiveArrayCritical(_precisionArray, (jboolean *) 0);
+        precision = (GLint *) (_precisionBase + _precisionBufferOffset);
+    }
     glGetShaderPrecisionFormat(
         (GLenum)shadertype,
         (GLenum)precisiontype,
         (GLint *)range,
         (GLint *)precision
     );
-    if (_rangeArray) {
-        releasePointer(_env, _rangeArray, precision, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_precisionArray) {
-        releasePointer(_env, _precisionArray, range, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _precisionArray, precision, JNI_TRUE);
+    }
+    if (_rangeArray) {
+        releasePointer(_env, _rangeArray, range, JNI_TRUE);
     }
 }
 
@@ -2847,6 +3560,8 @@
 android_glGetShaderSource__II_3II_3BI
   (JNIEnv *_env, jobject _this, jint shader, jint bufsize, jintArray length_ref, jint lengthOffset, jbyteArray source_ref, jint sourceOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *length_base = (GLsizei *) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
@@ -2856,12 +3571,14 @@
 
     if (!length_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -2871,12 +3588,14 @@
 
     if (!source_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "source == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "source == null";
         goto exit;
     }
     if (sourceOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "sourceOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sourceOffset < 0";
         goto exit;
     }
     _sourceRemaining = _env->GetArrayLength(source_ref) - sourceOffset;
@@ -2900,18 +3619,25 @@
         _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source ) */
 static void
 android_glGetShaderSource__IILjava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint shader, jint bufsize, jobject length_buf, jbyte source) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLsizei *length = (GLsizei *) 0;
 
-    length = (GLsizei *)getPointer(_env, length_buf, &_array, &_remaining);
+    length = (GLsizei *)getPointer(_env, length_buf, &_array, &_remaining, &_bufferOffset);
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _bufferOffset);
+    }
     glGetShaderSource(
         (GLuint)shader,
         (GLsizei)bufsize,
@@ -2919,10 +3645,27 @@
         (char *)source
     );
     if (_array) {
-        releasePointer(_env, _array, length, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, length, JNI_TRUE);
     }
 }
 
+/* void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source ) */
+static jstring android_glGetShaderSource(JNIEnv *_env, jobject, jint shader) {
+    GLint shaderLen = 0;
+    glGetShaderiv((GLuint)shader, GL_SHADER_SOURCE_LENGTH, &shaderLen);
+    if (!shaderLen) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(shaderLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+    glGetShaderSource(shader, shaderLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
 /* const GLubyte * glGetString ( GLenum name ) */
 static jstring android_glGetString(JNIEnv* _env, jobject, jint name) {
     const char* chars = (const char*) glGetString((GLenum) name);
@@ -2933,24 +3676,29 @@
 android_glGetTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2968,6 +3716,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -2975,16 +3726,24 @@
 android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -2995,6 +3754,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -3002,24 +3764,29 @@
 android_glGetTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -3037,6 +3804,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -3044,16 +3814,24 @@
 android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -3064,6 +3842,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetUniformfv ( GLuint program, GLint location, GLfloat *params ) */
@@ -3071,18 +3852,22 @@
 android_glGetUniformfv__II_3FI
   (JNIEnv *_env, jobject _this, jint program, jint location, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3101,25 +3886,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetUniformfv ( GLuint program, GLint location, GLfloat *params ) */
 static void
 android_glGetUniformfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint location, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetUniformfv(
         (GLuint)program,
         (GLint)location,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3128,18 +3920,22 @@
 android_glGetUniformiv__II_3II
   (JNIEnv *_env, jobject _this, jint program, jint location, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3158,25 +3954,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetUniformiv ( GLuint program, GLint location, GLint *params ) */
 static void
 android_glGetUniformiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint location, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetUniformiv(
         (GLuint)program,
         (GLint)location,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3184,11 +3987,15 @@
 static jint
 android_glGetUniformLocation__ILjava_lang_String_2
   (JNIEnv *_env, jobject _this, jint program, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     int _returnValue = 0;
     const char* _nativename = 0;
 
     if (!name) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -3203,6 +4010,9 @@
         _env->ReleaseStringUTFChars(name, _nativename);
     }
 
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -3211,18 +4021,22 @@
 android_glGetVertexAttribfv__II_3FI
   (JNIEnv *_env, jobject _this, jint index, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3241,25 +4055,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetVertexAttribfv ( GLuint index, GLenum pname, GLfloat *params ) */
 static void
 android_glGetVertexAttribfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetVertexAttribfv(
         (GLuint)index,
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3268,18 +4089,22 @@
 android_glGetVertexAttribiv__II_3II
   (JNIEnv *_env, jobject _this, jint index, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3298,25 +4123,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetVertexAttribiv ( GLuint index, GLenum pname, GLint *params ) */
 static void
 android_glGetVertexAttribiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetVertexAttribiv(
         (GLuint)index,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3449,12 +4281,16 @@
 static void
 android_glReadPixels__IIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
-    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    if (pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
+    }
     glReadPixels(
         (GLint)x,
         (GLint)y,
@@ -3465,7 +4301,7 @@
         (GLvoid *)pixels
     );
     if (_array) {
-        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, pixels, JNI_TRUE);
     }
 }
 
@@ -3514,7 +4350,11 @@
 static void
 android_glShaderBinary__I_3IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint n, jintArray shaders_ref, jint offset, jint binaryformat, jobject binary_buf, jint length) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     GLuint *shaders_base = (GLuint *) 0;
     jint _shadersRemaining;
     GLuint *shaders = (GLuint *) 0;
@@ -3522,11 +4362,15 @@
     GLvoid *binary = (GLvoid *) 0;
 
     if (!shaders_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "shaders == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "shaders == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _shadersRemaining = _env->GetArrayLength(shaders_ref) - offset;
@@ -3534,7 +4378,11 @@
         _env->GetPrimitiveArrayCritical(shaders_ref, (jboolean *)0);
     shaders = shaders_base + offset;
 
-    binary = (GLvoid *)getPointer(_env, binary_buf, &_array, &_binaryRemaining);
+    binary = (GLvoid *)getPointer(_env, binary_buf, &_array, &_binaryRemaining, &_bufferOffset);
+    if (binary == NULL) {
+        char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        binary = (GLvoid *) (_binaryBase + _bufferOffset);
+    }
     glShaderBinary(
         (GLsizei)n,
         (GLuint *)shaders,
@@ -3551,6 +4399,9 @@
         _env->ReleasePrimitiveArrayCritical(shaders_ref, shaders_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glShaderBinary ( GLsizei n, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length ) */
@@ -3558,14 +4409,24 @@
 android_glShaderBinary__ILjava_nio_IntBuffer_2ILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint n, jobject shaders_buf, jint binaryformat, jobject binary_buf, jint length) {
     jarray _shadersArray = (jarray) 0;
+    jint _shadersBufferOffset = (jint) 0;
     jarray _binaryArray = (jarray) 0;
+    jint _binaryBufferOffset = (jint) 0;
     jint _shadersRemaining;
     GLuint *shaders = (GLuint *) 0;
     jint _binaryRemaining;
     GLvoid *binary = (GLvoid *) 0;
 
-    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining);
-    binary = (GLvoid *)getPointer(_env, binary_buf, &_binaryArray, &_binaryRemaining);
+    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+    binary = (GLvoid *)getPointer(_env, binary_buf, &_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
+    if (shaders == NULL) {
+        char * _shadersBase = (char *)_env->GetPrimitiveArrayCritical(_shadersArray, (jboolean *) 0);
+        shaders = (GLuint *) (_shadersBase + _shadersBufferOffset);
+    }
+    if (binary == NULL) {
+        char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_binaryArray, (jboolean *) 0);
+        binary = (GLvoid *) (_binaryBase + _binaryBufferOffset);
+    }
     glShaderBinary(
         (GLsizei)n,
         (GLuint *)shaders,
@@ -3573,11 +4434,11 @@
         (GLvoid *)binary,
         (GLsizei)length
     );
-    if (_shadersArray) {
-        releasePointer(_env, _shadersArray, binary, JNI_FALSE);
-    }
     if (_binaryArray) {
-        releasePointer(_env, _binaryArray, shaders, JNI_FALSE);
+        releasePointer(_env, _binaryArray, binary, JNI_FALSE);
+    }
+    if (_shadersArray) {
+        releasePointer(_env, _shadersArray, shaders, JNI_FALSE);
     }
 }
 
@@ -3668,11 +4529,16 @@
 android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexImage2D(
         (GLenum)target,
@@ -3705,21 +4571,30 @@
 static void
 android_glTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3737,21 +4612,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -3762,6 +4650,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
@@ -3779,21 +4670,30 @@
 static void
 android_glTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -3811,21 +4711,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -3836,6 +4749,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) */
@@ -3843,11 +4759,16 @@
 android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexSubImage2D(
         (GLenum)target,
@@ -3879,16 +4800,23 @@
 static void
 android_glUniform1fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -3907,6 +4835,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform1fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -3914,10 +4845,15 @@
 android_glUniform1fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform1fv(
         (GLint)location,
         (GLsizei)count,
@@ -3942,16 +4878,23 @@
 static void
 android_glUniform1iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -3970,6 +4913,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform1iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -3977,10 +4923,15 @@
 android_glUniform1iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform1iv(
         (GLint)location,
         (GLsizei)count,
@@ -4006,16 +4957,23 @@
 static void
 android_glUniform2fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4034,6 +4992,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform2fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -4041,10 +5002,15 @@
 android_glUniform2fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform2fv(
         (GLint)location,
         (GLsizei)count,
@@ -4070,16 +5036,23 @@
 static void
 android_glUniform2iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4098,6 +5071,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform2iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -4105,10 +5081,15 @@
 android_glUniform2iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform2iv(
         (GLint)location,
         (GLsizei)count,
@@ -4135,16 +5116,23 @@
 static void
 android_glUniform3fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4163,6 +5151,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform3fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -4170,10 +5161,15 @@
 android_glUniform3fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform3fv(
         (GLint)location,
         (GLsizei)count,
@@ -4200,16 +5196,23 @@
 static void
 android_glUniform3iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4228,6 +5231,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform3iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -4235,10 +5241,15 @@
 android_glUniform3iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform3iv(
         (GLint)location,
         (GLsizei)count,
@@ -4266,16 +5277,23 @@
 static void
 android_glUniform4fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4294,6 +5312,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform4fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -4301,10 +5322,15 @@
 android_glUniform4fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform4fv(
         (GLint)location,
         (GLsizei)count,
@@ -4332,16 +5358,23 @@
 static void
 android_glUniform4iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4360,6 +5393,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform4iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -4367,10 +5403,15 @@
 android_glUniform4iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform4iv(
         (GLint)location,
         (GLsizei)count,
@@ -4385,16 +5426,23 @@
 static void
 android_glUniformMatrix2fv__IIZ_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *value_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4414,6 +5462,9 @@
         _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniformMatrix2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -4421,10 +5472,15 @@
 android_glUniformMatrix2fv__IIZLjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
-    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining);
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
     glUniformMatrix2fv(
         (GLint)location,
         (GLsizei)count,
@@ -4440,16 +5496,23 @@
 static void
 android_glUniformMatrix3fv__IIZ_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *value_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4469,6 +5532,9 @@
         _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniformMatrix3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -4476,10 +5542,15 @@
 android_glUniformMatrix3fv__IIZLjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
-    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining);
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
     glUniformMatrix3fv(
         (GLint)location,
         (GLsizei)count,
@@ -4495,16 +5566,23 @@
 static void
 android_glUniformMatrix4fv__IIZ_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *value_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4524,6 +5602,9 @@
         _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniformMatrix4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -4531,10 +5612,15 @@
 android_glUniformMatrix4fv__IIZLjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
-    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining);
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
     glUniformMatrix4fv(
         (GLint)location,
         (GLsizei)count,
@@ -4578,16 +5664,23 @@
 static void
 android_glVertexAttrib1fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4605,6 +5698,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib1fv ( GLuint indx, const GLfloat *values ) */
@@ -4612,10 +5708,15 @@
 android_glVertexAttrib1fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib1fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4640,16 +5741,23 @@
 static void
 android_glVertexAttrib2fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4667,6 +5775,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib2fv ( GLuint indx, const GLfloat *values ) */
@@ -4674,10 +5785,15 @@
 android_glVertexAttrib2fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib2fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4703,16 +5819,23 @@
 static void
 android_glVertexAttrib3fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4730,6 +5853,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib3fv ( GLuint indx, const GLfloat *values ) */
@@ -4737,10 +5863,15 @@
 android_glVertexAttrib3fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib3fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4767,16 +5898,23 @@
 static void
 android_glVertexAttrib4fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4794,6 +5932,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib4fv ( GLuint indx, const GLfloat *values ) */
@@ -4801,10 +5942,15 @@
 android_glVertexAttrib4fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib4fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4833,6 +5979,7 @@
 android_glVertexAttribPointerBounds__IIIZILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint indx, jint size, jint type, jboolean normalized, jint stride, jobject ptr_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *ptr = (GLvoid *) 0;
 
@@ -4934,8 +6081,12 @@
 {"glGenTextures", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenTextures__ILjava_nio_IntBuffer_2 },
 {"glGetActiveAttrib", "(III[II[II[II[BI)V", (void *) android_glGetActiveAttrib__III_3II_3II_3II_3BI },
 {"glGetActiveAttrib", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetActiveAttrib__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetActiveAttrib", "(II[II[II)Ljava/lang/String;", (void *) android_glGetActiveAttrib1 },
+{"glGetActiveAttrib", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetActiveAttrib2 },
 {"glGetActiveUniform", "(III[II[II[II[BI)V", (void *) android_glGetActiveUniform__III_3II_3II_3II_3BI },
+{"glGetActiveUniform", "(II[II[II)Ljava/lang/String;", (void *) android_glGetActiveUniform1 },
 {"glGetActiveUniform", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetActiveUniform__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetActiveUniform", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetActiveUniform2 },
 {"glGetAttachedShaders", "(II[II[II)V", (void *) android_glGetAttachedShaders__II_3II_3II },
 {"glGetAttachedShaders", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)V", (void *) android_glGetAttachedShaders__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
 {"glGetAttribLocation", "(ILjava/lang/String;)I", (void *) android_glGetAttribLocation__ILjava_lang_String_2 },
@@ -4962,6 +6113,7 @@
 {"glGetShaderPrecisionFormat", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)V", (void *) android_glGetShaderPrecisionFormat__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
 {"glGetShaderSource", "(II[II[BI)V", (void *) android_glGetShaderSource__II_3II_3BI },
 {"glGetShaderSource", "(IILjava/nio/IntBuffer;B)V", (void *) android_glGetShaderSource__IILjava_nio_IntBuffer_2B },
+{"glGetShaderSource", "(I)Ljava/lang/String;", (void *) android_glGetShaderSource },
 {"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },
 {"glGetTexParameterfv", "(II[FI)V", (void *) android_glGetTexParameterfv__II_3FI },
 {"glGetTexParameterfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2 },
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index 66d58cd..78f989a 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -112,6 +112,15 @@
 }
 
 /*
+ * public static native long elapsedRealtimeNano();
+ */
+static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env,
+        jobject clazz)
+{
+    return (jlong)elapsedRealtimeNano();
+}
+
+/*
  * JNI registration.
  */
 static JNINativeMethod gMethods[] = {
@@ -128,6 +137,8 @@
             (void*) android_os_SystemClock_currentThreadTimeMicro },
     { "currentTimeMicro",             "()J",
             (void*) android_os_SystemClock_currentTimeMicro },
+    { "elapsedRealtimeNano",      "()J",
+            (void*) android_os_SystemClock_elapsedRealtimeNano },
 };
 int register_android_os_SystemClock(JNIEnv* env)
 {
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
deleted file mode 100644
index d065a9e..0000000
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BluetoothA2dpService.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static jmethodID method_onSinkPropertyChanged;
-static jmethodID method_onConnectSinkResult;
-
-typedef struct {
-    JavaVM *vm;
-    int envVer;
-    DBusConnection *conn;
-    jobject me;  // for callbacks to java
-} native_data_t;
-
-static native_data_t *nat = NULL;  // global native data
-static void onConnectSinkResult(DBusMessage *msg, void *user, void *n);
-
-static Properties sink_properties[] = {
-        {"State", DBUS_TYPE_STRING},
-        {"Connected", DBUS_TYPE_BOOLEAN},
-        {"Playing", DBUS_TYPE_BOOLEAN},
-      };
-#endif
-
-/* Returns true on success (even if adapter is present but disabled).
- * Return false if dbus is down, or another serious error (out of memory)
-*/
-static bool initNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return false;
-    }
-    env->GetJavaVM( &(nat->vm) );
-    nat->envVer = env->GetVersion();
-    nat->me = env->NewGlobalRef(object);
-
-    DBusError err;
-    dbus_error_init(&err);
-    dbus_threads_init_default();
-    nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-    if (dbus_error_is_set(&err)) {
-        ALOGE("Could not get onto the system bus: %s", err.message);
-        dbus_error_free(&err);
-        return false;
-    }
-    dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
-#endif  /*HAVE_BLUETOOTH*/
-    return true;
-}
-
-static void cleanupNative(JNIEnv* env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        dbus_connection_close(nat->conn);
-        env->DeleteGlobalRef(nat->me);
-        free(nat);
-        nat = NULL;
-    }
-#endif
-}
-
-static jobjectArray getSinkPropertiesNative(JNIEnv *env, jobject object,
-                                            jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        reply = dbus_func_args_timeout(env,
-                                   nat->conn, -1, c_path,
-                                   "org.bluez.AudioSink", "GetProperties",
-                                   DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        if (!reply && dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-            return NULL;
-        } else if (!reply) {
-            ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return NULL;
-        }
-        DBusMessageIter iter;
-        if (dbus_message_iter_init(reply, &iter))
-            return parse_properties(env, &iter, (Properties *)&sink_properties,
-                                 sizeof(sink_properties) / sizeof(Properties));
-    }
-#endif
-    return NULL;
-}
-
-
-static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, context_path,
-                                    nat, c_path, "org.bluez.AudioSink", "Connect",
-                                    DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectSinkNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                                    c_path, "org.bluez.AudioSink", "Disconnect",
-                                    DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean suspendSinkNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.audio.Sink", "Suspend",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean resumeSinkNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.audio.Sink", "Resume",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.Control", "VolumeUp",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.Control", "VolumeDown",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-#ifdef HAVE_BLUETOOTH
-DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) {
-    DBusError err;
-
-    if (!nat) {
-        ALOGV("... skipping %s\n", __FUNCTION__);
-        ALOGV("... ignored\n");
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    dbus_error_init(&err);
-
-    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-    if (dbus_message_is_signal(msg, "org.bluez.AudioSink",
-                                      "PropertyChanged")) {
-        jobjectArray str_array =
-                    parse_property_change(env, msg, (Properties *)&sink_properties,
-                                sizeof(sink_properties) / sizeof(Properties));
-        const char *c_path = dbus_message_get_path(msg);
-        jstring path = env->NewStringUTF(c_path);
-        env->CallVoidMethod(nat->me,
-                            method_onSinkPropertyChanged,
-                            path,
-                            str_array);
-        env->DeleteLocalRef(path);
-        result = DBUS_HANDLER_RESULT_HANDLED;
-        return result;
-    } else {
-        ALOGV("... ignored");
-    }
-    if (env->ExceptionCheck()) {
-        ALOGE("VM Exception occurred while handling %s.%s (%s) in %s,"
-             " leaving for VM",
-             dbus_message_get_interface(msg), dbus_message_get_member(msg),
-             dbus_message_get_path(msg), __FUNCTION__);
-    }
-
-    return result;
-}
-
-void onConnectSinkResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-
-    bool result = JNI_TRUE;
-    if (dbus_set_error_from_message(&err, msg)) {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-        result = JNI_FALSE;
-    }
-    ALOGV("... Device Path = %s, result = %d", path, result);
-
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onConnectSinkResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-
-#endif
-
-
-static JNINativeMethod sMethods[] = {
-    {"initNative", "()Z", (void *)initNative},
-    {"cleanupNative", "()V", (void *)cleanupNative},
-
-    /* Bluez audio 4.47 API */
-    {"connectSinkNative", "(Ljava/lang/String;)Z", (void *)connectSinkNative},
-    {"disconnectSinkNative", "(Ljava/lang/String;)Z", (void *)disconnectSinkNative},
-    {"suspendSinkNative", "(Ljava/lang/String;)Z", (void*)suspendSinkNative},
-    {"resumeSinkNative", "(Ljava/lang/String;)Z", (void*)resumeSinkNative},
-    {"getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
-                                    (void *)getSinkPropertiesNative},
-    {"avrcpVolumeUpNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeUpNative},
-    {"avrcpVolumeDownNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeDownNative},
-};
-
-int register_android_server_BluetoothA2dpService(JNIEnv *env) {
-    jclass clazz = env->FindClass("android/server/BluetoothA2dpService");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/server/BluetoothA2dpService");
-        return -1;
-    }
-
-#ifdef HAVE_BLUETOOTH
-    method_onSinkPropertyChanged = env->GetMethodID(clazz, "onSinkPropertyChanged",
-                                          "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onConnectSinkResult = env->GetMethodID(clazz, "onConnectSinkResult",
-                                                         "(Ljava/lang/String;Z)V");
-#endif
-
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/server/BluetoothA2dpService", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
deleted file mode 100644
index 8a69ba4..0000000
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ /dev/null
@@ -1,1585 +0,0 @@
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BluetoothEventLoop.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "cutils/sockets.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#define CREATE_DEVICE_ALREADY_EXISTS 1
-#define CREATE_DEVICE_SUCCESS 0
-#define CREATE_DEVICE_FAILED -1
-
-#ifdef HAVE_BLUETOOTH
-static jfieldID field_mNativeData;
-
-static jmethodID method_onPropertyChanged;
-static jmethodID method_onDevicePropertyChanged;
-static jmethodID method_onDeviceFound;
-static jmethodID method_onDeviceDisappeared;
-static jmethodID method_onDeviceCreated;
-static jmethodID method_onDeviceRemoved;
-static jmethodID method_onDeviceDisconnectRequested;
-static jmethodID method_onNetworkDeviceDisconnected;
-static jmethodID method_onNetworkDeviceConnected;
-
-static jmethodID method_onCreatePairedDeviceResult;
-static jmethodID method_onCreateDeviceResult;
-static jmethodID method_onDiscoverServicesResult;
-static jmethodID method_onGetDeviceServiceChannelResult;
-
-static jmethodID method_onRequestPinCode;
-static jmethodID method_onRequestPasskey;
-static jmethodID method_onRequestPasskeyConfirmation;
-static jmethodID method_onRequestPairingConsent;
-static jmethodID method_onDisplayPasskey;
-static jmethodID method_onRequestOobData;
-static jmethodID method_onAgentOutOfBandDataAvailable;
-static jmethodID method_onAgentAuthorize;
-static jmethodID method_onAgentCancel;
-
-static jmethodID method_onInputDevicePropertyChanged;
-static jmethodID method_onInputDeviceConnectionResult;
-static jmethodID method_onPanDevicePropertyChanged;
-static jmethodID method_onPanDeviceConnectionResult;
-static jmethodID method_onHealthDevicePropertyChanged;
-static jmethodID method_onHealthDeviceChannelChanged;
-static jmethodID method_onHealthDeviceConnectionResult;
-
-typedef event_loop_native_data_t native_data_t;
-
-#define EVENT_LOOP_REFS 10
-
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    return (native_data_t *)(env->GetIntField(object,
-                                                 field_mNativeData));
-}
-
-native_data_t *get_EventLoop_native_data(JNIEnv *env, jobject object) {
-    return get_native_data(env, object);
-}
-
-#endif
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-
-#ifdef HAVE_BLUETOOTH
-    method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged",
-                                                "([Ljava/lang/String;)V");
-    method_onDevicePropertyChanged = env->GetMethodID(clazz,
-                                                      "onDevicePropertyChanged",
-                                                      "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onDeviceFound = env->GetMethodID(clazz, "onDeviceFound",
-                                            "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onDeviceDisappeared = env->GetMethodID(clazz, "onDeviceDisappeared",
-                                                  "(Ljava/lang/String;)V");
-    method_onDeviceCreated = env->GetMethodID(clazz, "onDeviceCreated", "(Ljava/lang/String;)V");
-    method_onDeviceRemoved = env->GetMethodID(clazz, "onDeviceRemoved", "(Ljava/lang/String;)V");
-    method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested",
-                                                        "(Ljava/lang/String;)V");
-    method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected",
-                                                     "(Ljava/lang/String;Ljava/lang/String;I)V");
-    method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected",
-                                                              "(Ljava/lang/String;)V");
-
-    method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult",
-                                                         "(Ljava/lang/String;I)V");
-    method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult",
-                                                         "(Ljava/lang/String;I)V");
-    method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult",
-                                                         "(Ljava/lang/String;Z)V");
-
-    method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize",
-                                               "(Ljava/lang/String;Ljava/lang/String;I)V");
-    method_onAgentOutOfBandDataAvailable = env->GetMethodID(clazz, "onAgentOutOfBandDataAvailable",
-                                               "(Ljava/lang/String;)Z");
-    method_onAgentCancel = env->GetMethodID(clazz, "onAgentCancel", "()V");
-    method_onRequestPinCode = env->GetMethodID(clazz, "onRequestPinCode",
-                                               "(Ljava/lang/String;I)V");
-    method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
-                                               "(Ljava/lang/String;I)V");
-    method_onRequestPasskeyConfirmation = env->GetMethodID(clazz, "onRequestPasskeyConfirmation",
-                                               "(Ljava/lang/String;II)V");
-    method_onRequestPairingConsent = env->GetMethodID(clazz, "onRequestPairingConsent",
-                                               "(Ljava/lang/String;I)V");
-    method_onDisplayPasskey = env->GetMethodID(clazz, "onDisplayPasskey",
-                                               "(Ljava/lang/String;II)V");
-    method_onInputDevicePropertyChanged = env->GetMethodID(clazz, "onInputDevicePropertyChanged",
-                                               "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onInputDeviceConnectionResult = env->GetMethodID(clazz, "onInputDeviceConnectionResult",
-                                               "(Ljava/lang/String;I)V");
-    method_onPanDevicePropertyChanged = env->GetMethodID(clazz, "onPanDevicePropertyChanged",
-                                               "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
-                                               "(Ljava/lang/String;I)V");
-    method_onHealthDeviceConnectionResult = env->GetMethodID(clazz,
-                                                             "onHealthDeviceConnectionResult",
-                                                             "(II)V");
-    method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged",
-                                               "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged",
-                                               "(Ljava/lang/String;Ljava/lang/String;Z)V");
-    method_onRequestOobData = env->GetMethodID(clazz, "onRequestOobData",
-                                               "(Ljava/lang/String;I)V");
-
-    field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return;
-    }
-
-    pthread_mutex_init(&(nat->thread_mutex), NULL);
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-
-    {
-        DBusError err;
-        dbus_error_init(&err);
-        dbus_threads_init_default();
-        nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-        if (dbus_error_is_set(&err)) {
-            ALOGE("%s: Could not get onto the system bus!", __FUNCTION__);
-            dbus_error_free(&err);
-        }
-        dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
-    }
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-            (native_data_t *)env->GetIntField(object, field_mNativeData);
-
-    pthread_mutex_destroy(&(nat->thread_mutex));
-
-    if (nat) {
-        free(nat);
-    }
-#endif
-}
-
-#ifdef HAVE_BLUETOOTH
-static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
-                                      void *data);
-DBusHandlerResult agent_event_filter(DBusConnection *conn,
-                                     DBusMessage *msg,
-                                     void *data);
-static int register_agent(native_data_t *nat,
-                          const char *agent_path, const char *capabilities);
-
-static const DBusObjectPathVTable agent_vtable = {
-    NULL, agent_event_filter, NULL, NULL, NULL, NULL
-};
-
-static unsigned int unix_events_to_dbus_flags(short events) {
-    return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
-           (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
-           (events & DBUS_WATCH_ERROR ? POLLERR : 0) |
-           (events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
-}
-
-static short dbus_flags_to_unix_events(unsigned int flags) {
-    return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) |
-           (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) |
-           (flags & POLLERR ? DBUS_WATCH_ERROR : 0) |
-           (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0);
-}
-
-static jboolean setUpEventLoop(native_data_t *nat) {
-    ALOGV("%s", __FUNCTION__);
-
-    if (nat != NULL && nat->conn != NULL) {
-        dbus_threads_init_default();
-        DBusError err;
-        dbus_error_init(&err);
-
-        const char *agent_path = "/android/bluetooth/agent";
-        const char *capabilities = "DisplayYesNo";
-        if (register_agent(nat, agent_path, capabilities) < 0) {
-            dbus_connection_unregister_object_path (nat->conn, agent_path);
-            return JNI_FALSE;
-        }
-
-        // Add a filter for all incoming messages
-        if (!dbus_connection_add_filter(nat->conn, event_filter, nat, NULL)){
-            return JNI_FALSE;
-        }
-
-        // Set which messages will be processed by this dbus connection
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='org.freedesktop.DBus'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='org.bluez.AudioSink'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-
-        return JNI_TRUE;
-    }
-    return JNI_FALSE;
-}
-
-
-const char * get_adapter_path(DBusConnection *conn) {
-    DBusMessage *msg = NULL, *reply = NULL;
-    DBusError err;
-    const char *device_path = NULL;
-    int attempt = 0;
-
-    for (attempt = 0; attempt < 1000 && reply == NULL; attempt ++) {
-        msg = dbus_message_new_method_call("org.bluez", "/",
-              "org.bluez.Manager", "DefaultAdapter");
-        if (!msg) {
-            ALOGE("%s: Can't allocate new method call for get_adapter_path!",
-                  __FUNCTION__);
-            return NULL;
-        }
-        dbus_message_append_args(msg, DBUS_TYPE_INVALID);
-        dbus_error_init(&err);
-        reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                if (dbus_error_has_name(&err,
-                    "org.freedesktop.DBus.Error.ServiceUnknown")) {
-                    // bluetoothd is still down, retry
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                    usleep(10000);  // 10 ms
-                    continue;
-                } else {
-                    // Some other error we weren't expecting
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                }
-            }
-            goto failed;
-        }
-    }
-    if (attempt == 1000) {
-        ALOGE("Time out while trying to get Adapter path, is bluetoothd up ?");
-        goto failed;
-    }
-
-    if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
-                               &device_path, DBUS_TYPE_INVALID)
-                               || !device_path){
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        goto failed;
-    }
-    dbus_message_unref(msg);
-    return device_path;
-
-failed:
-    dbus_message_unref(msg);
-    return NULL;
-}
-
-static int register_agent(native_data_t *nat,
-                          const char * agent_path, const char * capabilities)
-{
-    DBusMessage *msg, *reply;
-    DBusError err;
-    dbus_bool_t oob = TRUE;
-
-    if (!dbus_connection_register_object_path(nat->conn, agent_path,
-            &agent_vtable, nat)) {
-        ALOGE("%s: Can't register object path %s for agent!",
-              __FUNCTION__, agent_path);
-        return -1;
-    }
-
-    nat->adapter = get_adapter_path(nat->conn);
-    if (nat->adapter == NULL) {
-        return -1;
-    }
-    msg = dbus_message_new_method_call("org.bluez", nat->adapter,
-          "org.bluez.Adapter", "RegisterAgent");
-    if (!msg) {
-        ALOGE("%s: Can't allocate new method call for agent!",
-              __FUNCTION__);
-        return -1;
-    }
-    dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
-                             DBUS_TYPE_STRING, &capabilities,
-                             DBUS_TYPE_INVALID);
-
-    dbus_error_init(&err);
-    reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-    dbus_message_unref(msg);
-
-    if (!reply) {
-        ALOGE("%s: Can't register agent!", __FUNCTION__);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        return -1;
-    }
-
-    dbus_message_unref(reply);
-    dbus_connection_flush(nat->conn);
-
-    return 0;
-}
-
-static void tearDownEventLoop(native_data_t *nat) {
-    ALOGV("%s", __FUNCTION__);
-    if (nat != NULL && nat->conn != NULL) {
-
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-        const char * agent_path = "/android/bluetooth/agent";
-
-        msg = dbus_message_new_method_call("org.bluez",
-                                           nat->adapter,
-                                           "org.bluez.Adapter",
-                                           "UnregisterAgent");
-        if (msg != NULL) {
-            dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
-                                     DBUS_TYPE_INVALID);
-            reply = dbus_connection_send_with_reply_and_block(nat->conn,
-                                                              msg, -1, &err);
-
-            if (!reply) {
-                if (dbus_error_is_set(&err)) {
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                    dbus_error_free(&err);
-                }
-            } else {
-                dbus_message_unref(reply);
-            }
-            dbus_message_unref(msg);
-        } else {
-             ALOGE("%s: Can't create new method call!", __FUNCTION__);
-        }
-
-        dbus_connection_flush(nat->conn);
-        dbus_connection_unregister_object_path(nat->conn, agent_path);
-
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".AudioSink'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='org.bluez.audio.Manager'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='org.freedesktop.DBus'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-
-        dbus_connection_remove_filter(nat->conn, event_filter, nat);
-    }
-}
-
-
-#define EVENT_LOOP_EXIT 1
-#define EVENT_LOOP_ADD  2
-#define EVENT_LOOP_REMOVE 3
-#define EVENT_LOOP_WAKEUP 4
-
-dbus_bool_t dbusAddWatch(DBusWatch *watch, void *data) {
-    native_data_t *nat = (native_data_t *)data;
-
-    if (dbus_watch_get_enabled(watch)) {
-        // note that we can't just send the watch and inspect it later
-        // because we may get a removeWatch call before this data is reacted
-        // to by our eventloop and remove this watch..  reading the add first
-        // and then inspecting the recently deceased watch would be bad.
-        char control = EVENT_LOOP_ADD;
-        write(nat->controlFdW, &control, sizeof(char));
-
-        int fd = dbus_watch_get_fd(watch);
-        write(nat->controlFdW, &fd, sizeof(int));
-
-        unsigned int flags = dbus_watch_get_flags(watch);
-        write(nat->controlFdW, &flags, sizeof(unsigned int));
-
-        write(nat->controlFdW, &watch, sizeof(DBusWatch*));
-    }
-    return true;
-}
-
-void dbusRemoveWatch(DBusWatch *watch, void *data) {
-    native_data_t *nat = (native_data_t *)data;
-
-    char control = EVENT_LOOP_REMOVE;
-    write(nat->controlFdW, &control, sizeof(char));
-
-    int fd = dbus_watch_get_fd(watch);
-    write(nat->controlFdW, &fd, sizeof(int));
-
-    unsigned int flags = dbus_watch_get_flags(watch);
-    write(nat->controlFdW, &flags, sizeof(unsigned int));
-}
-
-void dbusToggleWatch(DBusWatch *watch, void *data) {
-    if (dbus_watch_get_enabled(watch)) {
-        dbusAddWatch(watch, data);
-    } else {
-        dbusRemoveWatch(watch, data);
-    }
-}
-
-void dbusWakeup(void *data) {
-    native_data_t *nat = (native_data_t *)data;
-
-    char control = EVENT_LOOP_WAKEUP;
-    write(nat->controlFdW, &control, sizeof(char));
-}
-
-static void handleWatchAdd(native_data_t *nat) {
-    DBusWatch *watch;
-    int newFD;
-    unsigned int flags;
-
-    read(nat->controlFdR, &newFD, sizeof(int));
-    read(nat->controlFdR, &flags, sizeof(unsigned int));
-    read(nat->controlFdR, &watch, sizeof(DBusWatch *));
-    short events = dbus_flags_to_unix_events(flags);
-
-    for (int y = 0; y<nat->pollMemberCount; y++) {
-        if ((nat->pollData[y].fd == newFD) &&
-                (nat->pollData[y].events == events)) {
-            ALOGV("DBusWatch duplicate add");
-            return;
-        }
-    }
-    if (nat->pollMemberCount == nat->pollDataSize) {
-        ALOGV("Bluetooth EventLoop poll struct growing");
-        struct pollfd *temp = (struct pollfd *)malloc(
-                sizeof(struct pollfd) * (nat->pollMemberCount+1));
-        if (!temp) {
-            return;
-        }
-        memcpy(temp, nat->pollData, sizeof(struct pollfd) *
-                nat->pollMemberCount);
-        free(nat->pollData);
-        nat->pollData = temp;
-        DBusWatch **temp2 = (DBusWatch **)malloc(sizeof(DBusWatch *) *
-                (nat->pollMemberCount+1));
-        if (!temp2) {
-            return;
-        }
-        memcpy(temp2, nat->watchData, sizeof(DBusWatch *) *
-                nat->pollMemberCount);
-        free(nat->watchData);
-        nat->watchData = temp2;
-        nat->pollDataSize++;
-    }
-    nat->pollData[nat->pollMemberCount].fd = newFD;
-    nat->pollData[nat->pollMemberCount].revents = 0;
-    nat->pollData[nat->pollMemberCount].events = events;
-    nat->watchData[nat->pollMemberCount] = watch;
-    nat->pollMemberCount++;
-}
-
-static void handleWatchRemove(native_data_t *nat) {
-    int removeFD;
-    unsigned int flags;
-
-    read(nat->controlFdR, &removeFD, sizeof(int));
-    read(nat->controlFdR, &flags, sizeof(unsigned int));
-    short events = dbus_flags_to_unix_events(flags);
-
-    for (int y = 0; y < nat->pollMemberCount; y++) {
-        if ((nat->pollData[y].fd == removeFD) &&
-                (nat->pollData[y].events == events)) {
-            int newCount = --nat->pollMemberCount;
-            // copy the last live member over this one
-            nat->pollData[y].fd = nat->pollData[newCount].fd;
-            nat->pollData[y].events = nat->pollData[newCount].events;
-            nat->pollData[y].revents = nat->pollData[newCount].revents;
-            nat->watchData[y] = nat->watchData[newCount];
-            return;
-        }
-    }
-    ALOGW("WatchRemove given with unknown watch");
-}
-
-static void *eventLoopMain(void *ptr) {
-    native_data_t *nat = (native_data_t *)ptr;
-    JNIEnv *env;
-
-    JavaVMAttachArgs args;
-    char name[] = "BT EventLoop";
-    args.version = nat->envVer;
-    args.name = name;
-    args.group = NULL;
-
-    nat->vm->AttachCurrentThread(&env, &args);
-
-    dbus_connection_set_watch_functions(nat->conn, dbusAddWatch,
-            dbusRemoveWatch, dbusToggleWatch, ptr, NULL);
-    dbus_connection_set_wakeup_main_function(nat->conn, dbusWakeup, ptr, NULL);
-
-    nat->running = true;
-
-    while (1) {
-        for (int i = 0; i < nat->pollMemberCount; i++) {
-            if (!nat->pollData[i].revents) {
-                continue;
-            }
-            if (nat->pollData[i].fd == nat->controlFdR) {
-                char data;
-                while (recv(nat->controlFdR, &data, sizeof(char), MSG_DONTWAIT)
-                        != -1) {
-                    switch (data) {
-                    case EVENT_LOOP_EXIT:
-                    {
-                        dbus_connection_set_watch_functions(nat->conn,
-                                NULL, NULL, NULL, NULL, NULL);
-                        tearDownEventLoop(nat);
-                        nat->vm->DetachCurrentThread();
-
-                        int fd = nat->controlFdR;
-                        nat->controlFdR = 0;
-                        close(fd);
-                        return NULL;
-                    }
-                    case EVENT_LOOP_ADD:
-                    {
-                        handleWatchAdd(nat);
-                        break;
-                    }
-                    case EVENT_LOOP_REMOVE:
-                    {
-                        handleWatchRemove(nat);
-                        break;
-                    }
-                    case EVENT_LOOP_WAKEUP:
-                    {
-                        // noop
-                        break;
-                    }
-                    }
-                }
-            } else {
-                short events = nat->pollData[i].revents;
-                unsigned int flags = unix_events_to_dbus_flags(events);
-                dbus_watch_handle(nat->watchData[i], flags);
-                nat->pollData[i].revents = 0;
-                // can only do one - it may have caused a 'remove'
-                break;
-            }
-        }
-        while (dbus_connection_dispatch(nat->conn) ==
-                DBUS_DISPATCH_DATA_REMAINS) {
-        }
-
-        poll(nat->pollData, nat->pollMemberCount, -1);
-    }
-}
-#endif // HAVE_BLUETOOTH
-
-static jboolean startEventLoopNative(JNIEnv *env, jobject object) {
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    event_loop_native_data_t *nat = get_native_data(env, object);
-
-    pthread_mutex_lock(&(nat->thread_mutex));
-
-    nat->running = false;
-
-    if (nat->pollData) {
-        ALOGW("trying to start EventLoop a second time!");
-        pthread_mutex_unlock( &(nat->thread_mutex) );
-        return JNI_FALSE;
-    }
-
-    nat->pollData = (struct pollfd *)calloc(
-            DEFAULT_INITIAL_POLLFD_COUNT, sizeof(struct pollfd));
-    if (!nat->pollData) {
-        ALOGE("out of memory error starting EventLoop!");
-        goto done;
-    }
-
-    nat->watchData = (DBusWatch **)calloc(
-            DEFAULT_INITIAL_POLLFD_COUNT, sizeof(DBusWatch *));
-    if (!nat->watchData) {
-        ALOGE("out of memory error starting EventLoop!");
-        goto done;
-    }
-
-    nat->pollDataSize = DEFAULT_INITIAL_POLLFD_COUNT;
-    nat->pollMemberCount = 1;
-
-    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(nat->controlFdR))) {
-        ALOGE("Error getting BT control socket");
-        goto done;
-    }
-    nat->pollData[0].fd = nat->controlFdR;
-    nat->pollData[0].events = POLLIN;
-
-    env->GetJavaVM( &(nat->vm) );
-    nat->envVer = env->GetVersion();
-
-    nat->me = env->NewGlobalRef(object);
-
-    if (setUpEventLoop(nat) != JNI_TRUE) {
-        ALOGE("failure setting up Event Loop!");
-        goto done;
-    }
-
-    pthread_create(&(nat->thread), NULL, eventLoopMain, nat);
-    result = JNI_TRUE;
-
-done:
-    if (JNI_FALSE == result) {
-        if (nat->controlFdW) {
-            close(nat->controlFdW);
-            nat->controlFdW = 0;
-        }
-        if (nat->controlFdR) {
-            close(nat->controlFdR);
-            nat->controlFdR = 0;
-        }
-        if (nat->me) env->DeleteGlobalRef(nat->me);
-        nat->me = NULL;
-        if (nat->pollData) free(nat->pollData);
-        nat->pollData = NULL;
-        if (nat->watchData) free(nat->watchData);
-        nat->watchData = NULL;
-        nat->pollDataSize = 0;
-        nat->pollMemberCount = 0;
-    }
-
-    pthread_mutex_unlock(&(nat->thread_mutex));
-#endif // HAVE_BLUETOOTH
-    return result;
-}
-
-static void stopEventLoopNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    pthread_mutex_lock(&(nat->thread_mutex));
-    if (nat->pollData) {
-        char data = EVENT_LOOP_EXIT;
-        ssize_t t = write(nat->controlFdW, &data, sizeof(char));
-        void *ret;
-        pthread_join(nat->thread, &ret);
-
-        env->DeleteGlobalRef(nat->me);
-        nat->me = NULL;
-        free(nat->pollData);
-        nat->pollData = NULL;
-        free(nat->watchData);
-        nat->watchData = NULL;
-        nat->pollDataSize = 0;
-        nat->pollMemberCount = 0;
-
-        int fd = nat->controlFdW;
-        nat->controlFdW = 0;
-        close(fd);
-    }
-    nat->running = false;
-    pthread_mutex_unlock(&(nat->thread_mutex));
-#endif // HAVE_BLUETOOTH
-}
-
-static jboolean isEventLoopRunningNative(JNIEnv *env, jobject object) {
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    pthread_mutex_lock(&(nat->thread_mutex));
-    if (nat->running) {
-        result = JNI_TRUE;
-    }
-    pthread_mutex_unlock(&(nat->thread_mutex));
-
-#endif // HAVE_BLUETOOTH
-    return result;
-}
-
-#ifdef HAVE_BLUETOOTH
-extern DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env);
-
-// Called by dbus during WaitForAndDispatchEventNative()
-static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
-                                      void *data) {
-    native_data_t *nat;
-    JNIEnv *env;
-    DBusError err;
-    DBusHandlerResult ret;
-
-    dbus_error_init(&err);
-
-    nat = (native_data_t *)data;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
-        ALOGV("%s: not interested (not a signal).", __FUNCTION__);
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    ALOGV("%s: Received signal %s:%s from %s", __FUNCTION__,
-        dbus_message_get_interface(msg), dbus_message_get_member(msg),
-        dbus_message_get_path(msg));
-
-    env->PushLocalFrame(EVENT_LOOP_REFS);
-    if (dbus_message_is_signal(msg,
-                               "org.bluez.Adapter",
-                               "DeviceFound")) {
-        char *c_address;
-        DBusMessageIter iter;
-        jobjectArray str_array = NULL;
-        if (dbus_message_iter_init(msg, &iter)) {
-            dbus_message_iter_get_basic(&iter, &c_address);
-            if (dbus_message_iter_next(&iter))
-                str_array =
-                    parse_remote_device_properties(env, &iter);
-        }
-        if (str_array != NULL) {
-            env->CallVoidMethod(nat->me,
-                                method_onDeviceFound,
-                                env->NewStringUTF(c_address),
-                                str_array);
-        } else
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Adapter",
-                                     "DeviceDisappeared")) {
-        char *c_address;
-        if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_STRING, &c_address,
-                                  DBUS_TYPE_INVALID)) {
-            ALOGV("... address = %s", c_address);
-            env->CallVoidMethod(nat->me, method_onDeviceDisappeared,
-                                env->NewStringUTF(c_address));
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Adapter",
-                                     "DeviceCreated")) {
-        char *c_object_path;
-        if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                                  DBUS_TYPE_INVALID)) {
-            ALOGV("... address = %s", c_object_path);
-            env->CallVoidMethod(nat->me,
-                                method_onDeviceCreated,
-                                env->NewStringUTF(c_object_path));
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Adapter",
-                                     "DeviceRemoved")) {
-        char *c_object_path;
-        if (dbus_message_get_args(msg, &err,
-                                 DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                                 DBUS_TYPE_INVALID)) {
-           ALOGV("... Object Path = %s", c_object_path);
-           env->CallVoidMethod(nat->me,
-                               method_onDeviceRemoved,
-                               env->NewStringUTF(c_object_path));
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Adapter",
-                                      "PropertyChanged")) {
-        jobjectArray str_array = parse_adapter_property_change(env, msg);
-        if (str_array != NULL) {
-            /* Check if bluetoothd has (re)started, if so update the path. */
-            jstring property =(jstring) env->GetObjectArrayElement(str_array, 0);
-            const char *c_property = env->GetStringUTFChars(property, NULL);
-            if (!strncmp(c_property, "Powered", strlen("Powered"))) {
-                jstring value =
-                    (jstring) env->GetObjectArrayElement(str_array, 1);
-                const char *c_value = env->GetStringUTFChars(value, NULL);
-                if (!strncmp(c_value, "true", strlen("true")))
-                    nat->adapter = get_adapter_path(nat->conn);
-                env->ReleaseStringUTFChars(value, c_value);
-            }
-            env->ReleaseStringUTFChars(property, c_property);
-
-            env->CallVoidMethod(nat->me,
-                              method_onPropertyChanged,
-                              str_array);
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Device",
-                                      "PropertyChanged")) {
-        jobjectArray str_array = parse_remote_device_property_change(env, msg);
-        if (str_array != NULL) {
-            const char *remote_device_path = dbus_message_get_path(msg);
-            env->CallVoidMethod(nat->me,
-                            method_onDevicePropertyChanged,
-                            env->NewStringUTF(remote_device_path),
-                            str_array);
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Device",
-                                      "DisconnectRequested")) {
-        const char *remote_device_path = dbus_message_get_path(msg);
-        env->CallVoidMethod(nat->me,
-                            method_onDeviceDisconnectRequested,
-                            env->NewStringUTF(remote_device_path));
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Input",
-                                      "PropertyChanged")) {
-
-        jobjectArray str_array =
-                    parse_input_property_change(env, msg);
-        if (str_array != NULL) {
-            const char *c_path = dbus_message_get_path(msg);
-            env->CallVoidMethod(nat->me,
-                                method_onInputDevicePropertyChanged,
-                                env->NewStringUTF(c_path),
-                                str_array);
-        } else {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        }
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Network",
-                                     "PropertyChanged")) {
-
-       jobjectArray str_array =
-                   parse_pan_property_change(env, msg);
-       if (str_array != NULL) {
-           const char *c_path = dbus_message_get_path(msg);
-           env->CallVoidMethod(nat->me,
-                               method_onPanDevicePropertyChanged,
-                               env->NewStringUTF(c_path),
-                               str_array);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.NetworkServer",
-                                     "DeviceDisconnected")) {
-       char *c_address;
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_STRING, &c_address,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onNetworkDeviceDisconnected,
-                               env->NewStringUTF(c_address));
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.NetworkServer",
-                                     "DeviceConnected")) {
-       char *c_address;
-       char *c_iface;
-       uint16_t uuid;
-
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_STRING, &c_address,
-                                  DBUS_TYPE_STRING, &c_iface,
-                                  DBUS_TYPE_UINT16, &uuid,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onNetworkDeviceConnected,
-                               env->NewStringUTF(c_address),
-                               env->NewStringUTF(c_iface),
-                               uuid);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.HealthDevice",
-                                     "ChannelConnected")) {
-       const char *c_path = dbus_message_get_path(msg);
-       const char *c_channel_path;
-       jboolean exists = JNI_TRUE;
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_OBJECT_PATH, &c_channel_path,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onHealthDeviceChannelChanged,
-                               env->NewStringUTF(c_path),
-                               env->NewStringUTF(c_channel_path),
-                               exists);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.HealthDevice",
-                                     "ChannelDeleted")) {
-
-       const char *c_path = dbus_message_get_path(msg);
-       const char *c_channel_path;
-       jboolean exists = JNI_FALSE;
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_OBJECT_PATH, &c_channel_path,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onHealthDeviceChannelChanged,
-                               env->NewStringUTF(c_path),
-                               env->NewStringUTF(c_channel_path),
-                               exists);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.HealthDevice",
-                                     "PropertyChanged")) {
-        jobjectArray str_array =
-                    parse_health_device_property_change(env, msg);
-        if (str_array != NULL) {
-            const char *c_path = dbus_message_get_path(msg);
-            env->CallVoidMethod(nat->me,
-                                method_onHealthDevicePropertyChanged,
-                                env->NewStringUTF(c_path),
-                                str_array);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    }
-
-    ret = a2dp_event_filter(msg, env);
-    env->PopLocalFrame(NULL);
-    return ret;
-
-success:
-    env->PopLocalFrame(NULL);
-    return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-// Called by dbus during WaitForAndDispatchEventNative()
-DBusHandlerResult agent_event_filter(DBusConnection *conn,
-                                     DBusMessage *msg, void *data) {
-    native_data_t *nat = (native_data_t *)data;
-    JNIEnv *env;
-    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
-        ALOGV("%s: not interested (not a method call).", __FUNCTION__);
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-    ALOGI("%s: Received method %s:%s", __FUNCTION__,
-         dbus_message_get_interface(msg), dbus_message_get_member(msg));
-
-    if (nat == NULL) return DBUS_HANDLER_RESULT_HANDLED;
-
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-    env->PushLocalFrame(EVENT_LOOP_REFS);
-
-    if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "Cancel")) {
-        env->CallVoidMethod(nat->me, method_onAgentCancel);
-        // reply
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-            goto failure;
-        }
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(reply);
-        goto success;
-
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "Authorize")) {
-        char *object_path;
-        const char *uuid;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_STRING, &uuid,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for Authorize() method", __FUNCTION__);
-            goto failure;
-        }
-
-        ALOGV("... object_path = %s", object_path);
-        ALOGV("... uuid = %s", uuid);
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onAgentAuthorize,
-                env->NewStringUTF(object_path), env->NewStringUTF(uuid),
-                int(msg));
-
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "OutOfBandAvailable")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for OutOfBandData available() method", __FUNCTION__);
-            goto failure;
-        }
-
-        ALOGV("... object_path = %s", object_path);
-
-        bool available =
-            env->CallBooleanMethod(nat->me, method_onAgentOutOfBandDataAvailable,
-                env->NewStringUTF(object_path));
-
-
-        // reply
-        if (available) {
-            DBusMessage *reply = dbus_message_new_method_return(msg);
-            if (!reply) {
-                ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                goto failure;
-            }
-            dbus_connection_send(nat->conn, reply, NULL);
-            dbus_message_unref(reply);
-        } else {
-            DBusMessage *reply = dbus_message_new_error(msg,
-                    "org.bluez.Error.DoesNotExist", "OutofBand data not available");
-            if (!reply) {
-                ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                goto failure;
-            }
-            dbus_connection_send(nat->conn, reply, NULL);
-            dbus_message_unref(reply);
-        }
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestPinCode")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPinCode,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestPasskey")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPasskey,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestOobData")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestOobData() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestOobData,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "DisplayPasskey")) {
-        char *object_path;
-        uint32_t passkey;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_UINT32, &passkey,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onDisplayPasskey,
-                                       env->NewStringUTF(object_path),
-                                       passkey,
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestConfirmation")) {
-        char *object_path;
-        uint32_t passkey;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_UINT32, &passkey,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPasskeyConfirmation,
-                                       env->NewStringUTF(object_path),
-                                       passkey,
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestPairingConsent")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPairingConsent() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPairingConsent,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-                  "org.bluez.Agent", "Release")) {
-        // reply
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-            goto failure;
-        }
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(reply);
-        goto success;
-    } else {
-        ALOGV("%s:%s is ignored", dbus_message_get_interface(msg), dbus_message_get_member(msg));
-    }
-
-failure:
-    env->PopLocalFrame(NULL);
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-success:
-    env->PopLocalFrame(NULL);
-    return DBUS_HANDLER_RESULT_HANDLED;
-
-}
-#endif
-
-
-#ifdef HAVE_BLUETOOTH
-
-void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *address = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    jstring addr;
-
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    ALOGV("... address = %s", address);
-
-    jint result = BOND_RESULT_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) {
-            // Pins did not match, or remote device did not respond to pin
-            // request in time
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_FAILED;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationRejected")) {
-            // We rejected pairing, or the remote side rejected pairing. This
-            // happens if either side presses 'cancel' at the pairing dialog.
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_REJECTED;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationCanceled")) {
-            // Not sure if this happens
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_CANCELED;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.ConnectionAttemptFailed")) {
-            // Other device is not responding at all
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_REMOTE_DEVICE_DOWN;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AlreadyExists")) {
-            // already bonded
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_SUCCESS;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") &&
-                   !strcmp(err.message, "Bonding in progress")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            goto done;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") &&
-                   !strcmp(err.message, "Discover in progress")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_DISCOVERY_IN_PROGRESS;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.RepeatedAttempts")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_REPEATED_ATTEMPTS;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationTimeout")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_TIMEOUT;
-        } else {
-            ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
-            result = BOND_RESULT_ERROR;
-        }
-    }
-
-    addr = env->NewStringUTF(address);
-    env->CallVoidMethod(nat->me,
-                        method_onCreatePairedDeviceResult,
-                        addr,
-                        result);
-    env->DeleteLocalRef(addr);
-done:
-    dbus_error_free(&err);
-    free(user);
-}
-
-void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *address= (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    ALOGV("... Address = %s", address);
-
-    jint result = CREATE_DEVICE_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (dbus_error_has_name(&err, "org.bluez.Error.AlreadyExists")) {
-            result = CREATE_DEVICE_ALREADY_EXISTS;
-        } else {
-            result = CREATE_DEVICE_FAILED;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-    jstring addr = env->NewStringUTF(address);
-    env->CallVoidMethod(nat->me,
-                        method_onCreateDeviceResult,
-                        addr,
-                        result);
-    env->DeleteLocalRef(addr);
-    free(user);
-}
-
-void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    ALOGV("... Device Path = %s", path);
-
-    bool result = JNI_TRUE;
-    if (dbus_set_error_from_message(&err, msg)) {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-        result = JNI_FALSE;
-    }
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onDiscoverServicesResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    const char *address = (const char *) user;
-    native_data_t *nat = (native_data_t *) n;
-
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint channel = -2;
-
-    ALOGV("... address = %s", address);
-
-    if (dbus_set_error_from_message(&err, msg) ||
-        !dbus_message_get_args(msg, &err,
-                               DBUS_TYPE_INT32, &channel,
-                               DBUS_TYPE_INVALID)) {
-        ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
-        dbus_error_free(&err);
-    }
-
-done:
-    jstring addr = env->NewStringUTF(address);
-    env->CallVoidMethod(nat->me,
-                        method_onGetDeviceServiceChannelResult,
-                        addr,
-                        channel);
-    env->DeleteLocalRef(addr);
-    free(user);
-}
-
-void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint result = INPUT_OPERATION_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
-            result = INPUT_CONNECT_FAILED_ATTEMPT_FAILED;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".AlreadyConnected")) {
-            result = INPUT_CONNECT_FAILED_ALREADY_CONNECTED;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
-            // TODO():This is flaky, need to change Bluez to add new error codes
-            if (!strcmp(err.message, "Transport endpoint is not connected")) {
-              result = INPUT_DISCONNECT_FAILED_NOT_CONNECTED;
-            } else {
-              result = INPUT_OPERATION_GENERIC_FAILURE;
-            }
-        } else {
-            result = INPUT_OPERATION_GENERIC_FAILURE;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-
-    ALOGV("... Device Path = %s, result = %d", path, result);
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onInputDeviceConnectionResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint result = PAN_OPERATION_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
-            result = PAN_CONNECT_FAILED_ATTEMPT_FAILED;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
-            // TODO():This is flaky, need to change Bluez to add new error codes
-            if (!strcmp(err.message, "Device already connected")) {
-                result = PAN_CONNECT_FAILED_ALREADY_CONNECTED;
-            } else if (!strcmp(err.message, "Device not connected")) {
-                result = PAN_DISCONNECT_FAILED_NOT_CONNECTED;
-            } else {
-                result = PAN_OPERATION_GENERIC_FAILURE;
-            }
-        } else {
-            result = PAN_OPERATION_GENERIC_FAILURE;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-
-    ALOGV("... Pan Device Path = %s, result = %d", path, result);
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onPanDeviceConnectionResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint result = HEALTH_OPERATION_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".InvalidArgs")) {
-            result = HEALTH_OPERATION_INVALID_ARGS;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".HealthError")) {
-            result = HEALTH_OPERATION_ERROR;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotFound")) {
-            result = HEALTH_OPERATION_NOT_FOUND;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotAllowed")) {
-            result = HEALTH_OPERATION_NOT_ALLOWED;
-        } else {
-            result = HEALTH_OPERATION_GENERIC_FAILURE;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-
-    jint code = *(int *) user;
-    ALOGV("... Health Device Code = %d, result = %d", code, result);
-    env->CallVoidMethod(nat->me,
-                        method_onHealthDeviceConnectionResult,
-                        code,
-                        result);
-    free(user);
-}
-#endif
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-    {"classInitNative", "()V", (void *)classInitNative},
-    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"startEventLoopNative", "()V", (void *)startEventLoopNative},
-    {"stopEventLoopNative", "()V", (void *)stopEventLoopNative},
-    {"isEventLoopRunningNative", "()Z", (void *)isEventLoopRunningNative}
-};
-
-int register_android_server_BluetoothEventLoop(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-            "android/server/BluetoothEventLoop", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
deleted file mode 100644
index 6c11121..0000000
--- a/core/jni/android_server_BluetoothService.cpp
+++ /dev/null
@@ -1,1785 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter"
-#define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device"
-#define DBUS_INPUT_IFACE BLUEZ_DBUS_BASE_IFC ".Input"
-#define DBUS_NETWORK_IFACE BLUEZ_DBUS_BASE_IFC ".Network"
-#define DBUS_NETWORKSERVER_IFACE BLUEZ_DBUS_BASE_IFC ".NetworkServer"
-#define DBUS_HEALTH_MANAGER_PATH "/org/bluez"
-#define DBUS_HEALTH_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".HealthManager"
-#define DBUS_HEALTH_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".HealthDevice"
-#define DBUS_HEALTH_CHANNEL_IFACE BLUEZ_DBUS_BASE_IFC ".HealthChannel"
-
-#define LOG_TAG "BluetoothService.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_util_Binder.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#include <bluedroid/bluetooth.h>
-#endif
-
-#include <cutils/properties.h>
-
-namespace android {
-
-#define BLUETOOTH_CLASS_ERROR 0xFF000000
-#define PROPERTIES_NREFS 10
-
-#ifdef HAVE_BLUETOOTH
-// We initialize these variables when we load class
-// android.server.BluetoothService
-static jfieldID field_mNativeData;
-static jfieldID field_mEventLoop;
-
-typedef struct {
-    JNIEnv *env;
-    DBusConnection *conn;
-    const char *adapter;  // dbus object name of the local adapter
-} native_data_t;
-
-extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *,
-                                                           jobject);
-extern DBusHandlerResult agent_event_filter(DBusConnection *conn,
-                                            DBusMessage *msg,
-                                            void *data);
-void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *nat);
-void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat);
-void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat);
-void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-
-
-/** Get native data stored in the opaque (Java code maintained) pointer mNativeData
- *  Perform quick sanity check, if there are any problems return NULL
- */
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    native_data_t *nat =
-            (native_data_t *)(env->GetIntField(object, field_mNativeData));
-    if (nat == NULL || nat->conn == NULL) {
-        ALOGE("Uninitialized native data\n");
-        return NULL;
-    }
-    return nat;
-}
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mEventLoop = get_field(env, clazz, "mEventLoop",
-            "Landroid/server/BluetoothEventLoop;");
-#endif
-}
-
-/* Returns true on success (even if adapter is present but disabled).
- * Return false if dbus is down, or another serious error (out of memory)
-*/
-static bool initializeNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return false;
-    }
-    nat->env = env;
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-    DBusError err;
-    dbus_error_init(&err);
-    dbus_threads_init_default();
-    nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-    if (dbus_error_is_set(&err)) {
-        ALOGE("Could not get onto the system bus: %s", err.message);
-        dbus_error_free(&err);
-        return false;
-    }
-    dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
-#endif  /*HAVE_BLUETOOTH*/
-    return true;
-}
-
-static const char *get_adapter_path(JNIEnv* env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    event_loop_native_data_t *event_nat =
-        get_EventLoop_native_data(env, env->GetObjectField(object,
-                                                           field_mEventLoop));
-    if (event_nat == NULL)
-        return NULL;
-    return event_nat->adapter;
-#else
-    return NULL;
-#endif
-}
-
-// This function is called when the adapter is enabled.
-static jboolean setupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-        (native_data_t *)env->GetIntField(object, field_mNativeData);
-    event_loop_native_data_t *event_nat =
-        get_EventLoop_native_data(env, env->GetObjectField(object,
-                                                           field_mEventLoop));
-    // Register agent for remote devices.
-    const char *device_agent_path = "/android/bluetooth/remote_device_agent";
-    static const DBusObjectPathVTable agent_vtable = {
-                 NULL, agent_event_filter, NULL, NULL, NULL, NULL };
-
-    if (!dbus_connection_register_object_path(nat->conn, device_agent_path,
-                                              &agent_vtable, event_nat)) {
-        ALOGE("%s: Can't register object path %s for remote device agent!",
-                               __FUNCTION__, device_agent_path);
-        return JNI_FALSE;
-    }
-#endif /*HAVE_BLUETOOTH*/
-    return JNI_TRUE;
-}
-
-static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-               (native_data_t *)env->GetIntField(object, field_mNativeData);
-    if (nat != NULL) {
-        const char *device_agent_path =
-            "/android/bluetooth/remote_device_agent";
-        dbus_connection_unregister_object_path (nat->conn, device_agent_path);
-    }
-#endif /*HAVE_BLUETOOTH*/
-    return JNI_TRUE;
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-        (native_data_t *)env->GetIntField(object, field_mNativeData);
-    if (nat) {
-        free(nat);
-        nat = NULL;
-    }
-#endif
-}
-
-static jstring getAdapterPathNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        return (env->NewStringUTF(get_adapter_path(env, object)));
-    }
-#endif
-    return NULL;
-}
-
-
-static jboolean startDiscoveryNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    DBusError err;
-    const char *name;
-    jboolean ret = JNI_FALSE;
-
-    native_data_t *nat = get_native_data(env, object);
-    if (nat == NULL) {
-        goto done;
-    }
-
-    dbus_error_init(&err);
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                       get_adapter_path(env, object),
-                                       DBUS_ADAPTER_IFACE, "StartDiscovery");
-
-    if (msg == NULL) {
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        }
-        goto done;
-    }
-
-    /* Send the command. */
-    reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-    if (dbus_error_is_set(&err)) {
-         LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-         ret = JNI_FALSE;
-         goto done;
-    }
-
-    ret = JNI_TRUE;
-done:
-    if (reply) dbus_message_unref(reply);
-    if (msg) dbus_message_unref(msg);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean stopDiscoveryNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    DBusError err;
-    const char *name;
-    native_data_t *nat;
-    jboolean ret = JNI_FALSE;
-
-    dbus_error_init(&err);
-
-    nat = get_native_data(env, object);
-    if (nat == NULL) {
-        goto done;
-    }
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                       get_adapter_path(env, object),
-                                       DBUS_ADAPTER_IFACE, "StopDiscovery");
-    if (msg == NULL) {
-        if (dbus_error_is_set(&err))
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto done;
-    }
-
-    /* Send the command. */
-    reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-    if (dbus_error_is_set(&err)) {
-        if(strncmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized",
-                   strlen(BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized")) == 0) {
-            // hcid sends this if there is no active discovery to cancel
-            ALOGV("%s: There was no active discovery to cancel", __FUNCTION__);
-            dbus_error_free(&err);
-        } else {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        }
-        goto done;
-    }
-
-    ret = JNI_TRUE;
-done:
-    if (msg) dbus_message_unref(msg);
-    if (reply) dbus_message_unref(reply);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    DBusError err;
-    jbyte *hash, *randomizer;
-    jbyteArray byteArray = NULL;
-    int hash_len, r_len;
-    if (nat) {
-       DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "ReadLocalOutOfBandData",
-                           DBUS_TYPE_INVALID);
-       if (!reply) return NULL;
-
-       dbus_error_init(&err);
-       if (dbus_message_get_args(reply, &err,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hash_len,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &r_len,
-                                DBUS_TYPE_INVALID)) {
-          if (hash_len == 16 && r_len == 16) {
-               byteArray = env->NewByteArray(32);
-               if (byteArray) {
-                   env->SetByteArrayRegion(byteArray, 0, 16, hash);
-                   env->SetByteArrayRegion(byteArray, 16, 16, randomizer);
-               }
-           } else {
-               ALOGE("readAdapterOutOfBandDataNative: Hash len = %d, R len = %d",
-                                                                  hash_len, r_len);
-           }
-       } else {
-          LOG_AND_FREE_DBUS_ERROR(&err);
-       }
-       dbus_message_unref(reply);
-       return byteArray;
-    }
-#endif
-    return NULL;
-}
-
-static jboolean createPairedDeviceNative(JNIEnv *env, jobject object,
-                                         jstring address, jint timeout_ms) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        ALOGV("... address = %s", c_address);
-        char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
-        const char *capabilities = "DisplayYesNo";
-        const char *agent_path = "/android/bluetooth/remote_device_agent";
-
-        strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
-        bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms,
-                                        onCreatePairedDeviceResult, // callback
-                                        context_address,
-                                        eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "CreatePairedDevice",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_OBJECT_PATH, &agent_path,
-                                        DBUS_TYPE_STRING, &capabilities,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        return ret ? JNI_TRUE : JNI_FALSE;
-
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object,
-                                                jstring address, jint timeout_ms) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        ALOGV("... address = %s", c_address);
-        char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
-        const char *capabilities = "DisplayYesNo";
-        const char *agent_path = "/android/bluetooth/remote_device_agent";
-
-        strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
-        bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms,
-                                        onCreatePairedDeviceResult, // callback
-                                        context_address,
-                                        eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "CreatePairedDeviceOutOfBand",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_OBJECT_PATH, &agent_path,
-                                        DBUS_TYPE_STRING, &capabilities,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jint getDeviceServiceChannelNative(JNIEnv *env, jobject object,
-                                          jstring path,
-                                          jstring pattern, jint attr_id) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-    if (nat && eventLoopNat) {
-        const char *c_pattern = env->GetStringUTFChars(pattern, NULL);
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        ALOGV("... pattern = %s", c_pattern);
-        ALOGV("... attr_id = %#X", attr_id);
-        DBusMessage *reply =
-            dbus_func_args(env, nat->conn, c_path,
-                           DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
-                           DBUS_TYPE_STRING, &c_pattern,
-                           DBUS_TYPE_UINT16, &attr_id,
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(pattern, c_pattern);
-        env->ReleaseStringUTFChars(path, c_path);
-        return reply ? dbus_returns_int32(env, reply) : -1;
-    }
-#endif
-    return -1;
-}
-
-static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object,
-                                           jstring address) {
-    ALOGV("%s", __FUNCTION__);
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-        ALOGV("... address = %s", c_address);
-        DBusMessage *reply =
-            dbus_func_args_timeout(env, nat->conn, -1,
-                                   get_adapter_path(env, object),
-                                   DBUS_ADAPTER_IFACE, "CancelDeviceCreation",
-                                   DBUS_TYPE_STRING, &c_address,
-                                   DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            } else
-                ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return JNI_FALSE;
-        } else {
-            result = JNI_TRUE;
-        }
-        dbus_message_unref(reply);
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_object_path = env->GetStringUTFChars(object_path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "RemoveDevice",
-                                        DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(object_path, c_object_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jint enableNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    return bt_enable();
-#endif
-    return -1;
-}
-
-static jint disableNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    return bt_disable();
-#endif
-    return -1;
-}
-
-static jint isEnabledNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    return bt_is_enabled();
-#endif
-    return -1;
-}
-
-static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object,
-                                             jstring address, bool confirm,
-                                             int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply;
-        if (confirm) {
-            reply = dbus_message_new_method_return(msg);
-        } else {
-            reply = dbus_message_new_error(msg,
-                "org.bluez.Error.Rejected", "User rejected confirmation");
-        }
-
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or"
-                  "RequestPairingConsent to D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address,
-                         int passkey, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return Passkey code to "
-                 "D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(reply, DBUS_TYPE_UINT32, (uint32_t *)&passkey,
-                                 DBUS_TYPE_INVALID);
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstring address,
-                         jbyteArray hash, jbyteArray randomizer, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        jbyte *h_ptr = env->GetByteArrayElements(hash, NULL);
-        jbyte *r_ptr = env->GetByteArrayElements(randomizer, NULL);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return remote OOB data to "
-                 "D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(reply,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &h_ptr, 16,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &r_ptr, 16,
-                                DBUS_TYPE_INVALID);
-
-        env->ReleaseByteArrayElements(hash, h_ptr, 0);
-        env->ReleaseByteArrayElements(randomizer, r_ptr, 0);
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setAuthorizationNative(JNIEnv *env, jobject object, jstring address,
-                         jboolean val, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-  ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply;
-        if (val) {
-            reply = dbus_message_new_method_return(msg);
-        } else {
-            reply = dbus_message_new_error(msg,
-                    "org.bluez.Error.Rejected", "Authorization rejected");
-        }
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setPinNative(JNIEnv *env, jobject object, jstring address,
-                         jstring pin, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return PIN code to "
-                 "D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        const char *c_pin = env->GetStringUTFChars(pin, NULL);
-
-        dbus_message_append_args(reply, DBUS_TYPE_STRING, &c_pin,
-                                 DBUS_TYPE_INVALID);
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        env->ReleaseStringUTFChars(pin, c_pin);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean cancelPairingUserInputNative(JNIEnv *env, jobject object,
-                                            jstring address, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_error(msg,
-                "org.bluez.Error.Canceled", "Pairing User Input was canceled");
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return cancelUserInput to"
-                 "D-BUS\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jobjectArray getDevicePropertiesNative(JNIEnv *env, jobject object,
-                                                    jstring path)
-{
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        reply = dbus_func_args_timeout(env,
-                                   nat->conn, -1, c_path,
-                                   DBUS_DEVICE_IFACE, "GetProperties",
-                                   DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            } else
-                ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return NULL;
-        }
-        env->PushLocalFrame(PROPERTIES_NREFS);
-
-        DBusMessageIter iter;
-        jobjectArray str_array = NULL;
-        if (dbus_message_iter_init(reply, &iter))
-           str_array =  parse_remote_device_properties(env, &iter);
-        dbus_message_unref(reply);
-
-        return (jobjectArray) env->PopLocalFrame(str_array);
-    }
-#endif
-    return NULL;
-}
-
-static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        reply = dbus_func_args_timeout(env,
-                                   nat->conn, -1, get_adapter_path(env, object),
-                                   DBUS_ADAPTER_IFACE, "GetProperties",
-                                   DBUS_TYPE_INVALID);
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            } else
-                ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return NULL;
-        }
-        env->PushLocalFrame(PROPERTIES_NREFS);
-
-        DBusMessageIter iter;
-        jobjectArray str_array = NULL;
-        if (dbus_message_iter_init(reply, &iter))
-            str_array = parse_adapter_properties(env, &iter);
-        dbus_message_unref(reply);
-
-        return (jobjectArray) env->PopLocalFrame(str_array);
-    }
-#endif
-    return NULL;
-}
-
-static jboolean setAdapterPropertyNative(JNIEnv *env, jobject object, jstring key,
-                                         void *value, jint type) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg;
-        DBusMessageIter iter;
-        dbus_bool_t reply = JNI_FALSE;
-        const char *c_key = env->GetStringUTFChars(key, NULL);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                           get_adapter_path(env, object),
-                                           DBUS_ADAPTER_IFACE, "SetProperty");
-        if (!msg) {
-            ALOGE("%s: Can't allocate new method call for GetProperties!",
-                  __FUNCTION__);
-            env->ReleaseStringUTFChars(key, c_key);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID);
-        dbus_message_iter_init_append(msg, &iter);
-        append_variant(&iter, type, value);
-
-        // Asynchronous call - the callbacks come via propertyChange
-        reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1);
-        dbus_message_unref(msg);
-
-        env->ReleaseStringUTFChars(key, c_key);
-        return reply ? JNI_TRUE : JNI_FALSE;
-
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setAdapterPropertyStringNative(JNIEnv *env, jobject object, jstring key,
-                                               jstring value) {
-#ifdef HAVE_BLUETOOTH
-    const char *c_value = env->GetStringUTFChars(value, NULL);
-    jboolean ret =  setAdapterPropertyNative(env, object, key, (void *)&c_value, DBUS_TYPE_STRING);
-    env->ReleaseStringUTFChars(value, (char *)c_value);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setAdapterPropertyIntegerNative(JNIEnv *env, jobject object, jstring key,
-                                               jint value) {
-#ifdef HAVE_BLUETOOTH
-    return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_UINT32);
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setAdapterPropertyBooleanNative(JNIEnv *env, jobject object, jstring key,
-                                               jint value) {
-#ifdef HAVE_BLUETOOTH
-    return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_BOOLEAN);
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path,
-                                               jstring key, void *value, jint type) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg;
-        DBusMessageIter iter;
-        dbus_bool_t reply = JNI_FALSE;
-
-        const char *c_key = env->GetStringUTFChars(key, NULL);
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                          c_path, DBUS_DEVICE_IFACE, "SetProperty");
-        if (!msg) {
-            ALOGE("%s: Can't allocate new method call for device SetProperty!", __FUNCTION__);
-            env->ReleaseStringUTFChars(key, c_key);
-            env->ReleaseStringUTFChars(path, c_path);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID);
-        dbus_message_iter_init_append(msg, &iter);
-        append_variant(&iter, type, value);
-
-        // Asynchronous call - the callbacks come via Device propertyChange
-        reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1);
-        dbus_message_unref(msg);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(key, c_key);
-
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setDevicePropertyBooleanNative(JNIEnv *env, jobject object,
-                                                     jstring path, jstring key, jint value) {
-#ifdef HAVE_BLUETOOTH
-    return setDevicePropertyNative(env, object, path, key,
-                                        (void *)&value, DBUS_TYPE_BOOLEAN);
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setDevicePropertyStringNative(JNIEnv *env, jobject object,
-                                              jstring path, jstring key, jstring value) {
-#ifdef HAVE_BLUETOOTH
-    const char *c_value = env->GetStringUTFChars(value, NULL);
-    jboolean ret = setDevicePropertyNative(env, object, path, key,
-                                           (void *)&c_value, DBUS_TYPE_STRING);
-    env->ReleaseStringUTFChars(value, (char *)c_value);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean createDeviceNative(JNIEnv *env, jobject object,
-                                                jstring address) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        ALOGV("... address = %s", c_address);
-        char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
-        strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        onCreateDeviceResult,
-                                        context_address,
-                                        eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "CreateDevice",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean discoverServicesNative(JNIEnv *env, jobject object,
-                                               jstring path, jstring pattern) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *c_pattern = env->GetStringUTFChars(pattern, NULL);
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        ALOGV("... Object Path = %s", c_path);
-        ALOGV("... Pattern = %s, strlen = %d", c_pattern, strlen(c_pattern));
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        onDiscoverServicesResult,
-                                        context_path,
-                                        eventLoopNat,
-                                        c_path,
-                                        DBUS_DEVICE_IFACE,
-                                        "DiscoverServices",
-                                        DBUS_TYPE_STRING, &c_pattern,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(pattern, c_pattern);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-#ifdef HAVE_BLUETOOTH
-static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) {
-    jint *handles;
-    jintArray handleArray = NULL;
-    int len;
-
-    DBusError err;
-    dbus_error_init(&err);
-
-    if (dbus_message_get_args(reply, &err,
-                              DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len,
-                              DBUS_TYPE_INVALID)) {
-        handleArray = env->NewIntArray(len);
-        if (handleArray) {
-            env->SetIntArrayRegion(handleArray, 0, len, handles);
-        } else {
-            ALOGE("Null array in extract_handles");
-        }
-    } else {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-    return handleArray;
-}
-#endif
-
-static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object,
-                                                jintArray uuids) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    DBusMessage *reply = NULL;
-
-    native_data_t *nat = get_native_data(env, object);
-
-    jint* svc_classes = env->GetIntArrayElements(uuids, NULL);
-    if (!svc_classes) return NULL;
-
-    int len = env->GetArrayLength(uuids);
-    reply = dbus_func_args(env, nat->conn,
-                            get_adapter_path(env, object),
-                            DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
-                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
-                            &svc_classes, len, DBUS_TYPE_INVALID);
-    env->ReleaseIntArrayElements(uuids, svc_classes, 0);
-    return reply ? extract_handles(env, reply) : NULL;
-
-#endif
-    return NULL;
-}
-
-static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object,
-                                                   jintArray handles) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jint *values = env->GetIntArrayElements(handles, NULL);
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    if (values == NULL) return JNI_FALSE;
-
-    jsize len = env->GetArrayLength(handles);
-
-    reply = dbus_func_args(env, nat->conn,
-                            get_adapter_path(env, object),
-                            DBUS_ADAPTER_IFACE, "RemoveReservedServiceRecords",
-                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
-                            &values, len, DBUS_TYPE_INVALID);
-    env->ReleaseIntArrayElements(handles, values, 0);
-    return reply ? JNI_TRUE : JNI_FALSE;
-#endif
-    return JNI_FALSE;
-}
-
-static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object,
-        jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_name = env->GetStringUTFChars(name, NULL);
-        ALOGV("... name = %s", c_name);
-        ALOGV("... uuid1 = %llX", uuidMsb);
-        ALOGV("... uuid2 = %llX", uuidLsb);
-        ALOGV("... channel = %d", channel);
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
-                           DBUS_TYPE_STRING, &c_name,
-                           DBUS_TYPE_UINT64, &uuidMsb,
-                           DBUS_TYPE_UINT64, &uuidLsb,
-                           DBUS_TYPE_UINT16, &channel,
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(name, c_name);
-        return reply ? dbus_returns_uint32(env, reply) : -1;
-    }
-#endif
-    return -1;
-}
-
-static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        ALOGV("... handle = %X", handle);
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "RemoveServiceRecord",
-                           DBUS_TYPE_UINT32, &handle,
-                           DBUS_TYPE_INVALID);
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path,
-                                     jint num_slots) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_object_path = env->GetStringUTFChars(object_path, NULL);
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "SetLinkTimeout",
-                           DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                           DBUS_TYPE_UINT32, &num_slots,
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(object_path, c_object_path);
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult,
-                                        context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE,
-                                        "Connect",
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult,
-                                        context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE,
-                                        "Disconnect",
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value,
-                                            jstring src_role, jstring bridge) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *reply;
-        const char *c_role = env->GetStringUTFChars(src_role, NULL);
-        const char *c_bridge = env->GetStringUTFChars(bridge, NULL);
-        if (value) {
-            ALOGE("setBluetoothTetheringNative true");
-            reply = dbus_func_args(env, nat->conn,
-                                  get_adapter_path(env, object),
-                                  DBUS_NETWORKSERVER_IFACE,
-                                  "Register",
-                                  DBUS_TYPE_STRING, &c_role,
-                                  DBUS_TYPE_STRING, &c_bridge,
-                                  DBUS_TYPE_INVALID);
-        } else {
-            ALOGE("setBluetoothTetheringNative false");
-            reply = dbus_func_args(env, nat->conn,
-                                  get_adapter_path(env, object),
-                                  DBUS_NETWORKSERVER_IFACE,
-                                  "Unregister",
-                                  DBUS_TYPE_STRING, &c_role,
-                                  DBUS_TYPE_INVALID);
-        }
-        env->ReleaseStringUTFChars(src_role, c_role);
-        env->ReleaseStringUTFChars(bridge, c_bridge);
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path,
-                                       jstring dstRole) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    ALOGE("connectPanDeviceNative");
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *dst = env->GetStringUTFChars(dstRole, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult,
-                                    context_path, eventLoopNat, c_path,
-                                    DBUS_NETWORK_IFACE, "Connect",
-                                    DBUS_TYPE_STRING, &dst,
-                                    DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(dstRole, dst);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    ALOGE("disconnectPanDeviceNative");
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult,
-                                        context_path, eventLoopNat, c_path,
-                                        DBUS_NETWORK_IFACE, "Disconnect",
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object,
-                                                jstring path, jstring address,
-                                                jstring iface) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    ALOGE("disconnectPanServerDeviceNative");
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *c_iface = env->GetStringUTFChars(iface, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        onPanDeviceConnectionResult,
-                                        context_path, eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_NETWORKSERVER_IFACE,
-                                        "DisconnectDevice",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_STRING, &c_iface,
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(address, c_address);
-        env->ReleaseStringUTFChars(iface, c_iface);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jstring registerHealthApplicationNative(JNIEnv *env, jobject object,
-                                           jint dataType, jstring role,
-                                           jstring name, jstring channelType) {
-    ALOGV("%s", __FUNCTION__);
-    jstring path = NULL;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_role = env->GetStringUTFChars(role, NULL);
-        const char *c_name = env->GetStringUTFChars(name, NULL);
-        const char *c_channel_type = env->GetStringUTFChars(channelType, NULL);
-        char *c_path;
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                            DBUS_HEALTH_MANAGER_PATH,
-                                            DBUS_HEALTH_MANAGER_IFACE,
-                                            "CreateApplication");
-
-        if (msg == NULL) {
-            ALOGE("Could not allocate D-Bus message object!");
-            return NULL;
-        }
-
-        /* append arguments */
-        append_dict_args(msg,
-                         "DataType", DBUS_TYPE_UINT16, &dataType,
-                         "Role", DBUS_TYPE_STRING, &c_role,
-                         "Description", DBUS_TYPE_STRING, &c_name,
-                         "ChannelType", DBUS_TYPE_STRING, &c_channel_type,
-                         DBUS_TYPE_INVALID);
-
-
-        /* Make the call. */
-        reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-
-        env->ReleaseStringUTFChars(role, c_role);
-        env->ReleaseStringUTFChars(name, c_name);
-        env->ReleaseStringUTFChars(channelType, c_channel_type);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            if (!dbus_message_get_args(reply, &err,
-                                      DBUS_TYPE_OBJECT_PATH, &c_path,
-                                      DBUS_TYPE_INVALID)) {
-                if (dbus_error_is_set(&err)) {
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                }
-            } else {
-               path = env->NewStringUTF(c_path);
-            }
-            dbus_message_unref(reply);
-        }
-    }
-#endif
-    return path;
-}
-
-static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object,
-                                           jint dataType, jstring role,
-                                           jstring name) {
-    ALOGV("%s", __FUNCTION__);
-    jstring path = NULL;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_role = env->GetStringUTFChars(role, NULL);
-        const char *c_name = env->GetStringUTFChars(name, NULL);
-        char *c_path;
-
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                            DBUS_HEALTH_MANAGER_PATH,
-                                            DBUS_HEALTH_MANAGER_IFACE,
-                                            "CreateApplication");
-
-        if (msg == NULL) {
-            ALOGE("Could not allocate D-Bus message object!");
-            return NULL;
-        }
-
-        /* append arguments */
-        append_dict_args(msg,
-                         "DataType", DBUS_TYPE_UINT16, &dataType,
-                         "Role", DBUS_TYPE_STRING, &c_role,
-                         "Description", DBUS_TYPE_STRING, &c_name,
-                         DBUS_TYPE_INVALID);
-
-
-        /* Make the call. */
-        reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-
-        env->ReleaseStringUTFChars(role, c_role);
-        env->ReleaseStringUTFChars(name, c_name);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            if (!dbus_message_get_args(reply, &err,
-                                      DBUS_TYPE_OBJECT_PATH, &c_path,
-                                      DBUS_TYPE_INVALID)) {
-                if (dbus_error_is_set(&err)) {
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                }
-            } else {
-                path = env->NewStringUTF(c_path);
-            }
-            dbus_message_unref(reply);
-        }
-    }
-#endif
-    return path;
-}
-
-static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object,
-                                                    jstring path) {
-    ALOGV("%s", __FUNCTION__);
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-        DBusMessage *reply =
-            dbus_func_args_timeout(env, nat->conn, -1,
-                                   DBUS_HEALTH_MANAGER_PATH,
-                                   DBUS_HEALTH_MANAGER_IFACE, "DestroyApplication",
-                                   DBUS_TYPE_OBJECT_PATH, &c_path,
-                                   DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            result = JNI_TRUE;
-        }
-    }
-#endif
-    return result;
-}
-
-static jboolean createChannelNative(JNIEnv *env, jobject object,
-                                       jstring devicePath, jstring appPath, jstring config,
-                                       jint code) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
-        const char *c_app_path = env->GetStringUTFChars(appPath, NULL);
-        const char *c_config = env->GetStringUTFChars(config, NULL);
-        int *data = (int *) malloc(sizeof(int));
-        if (data == NULL) return JNI_FALSE;
-
-        *data = code;
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
-                                        data, eventLoopNat, c_device_path,
-                                        DBUS_HEALTH_DEVICE_IFACE, "CreateChannel",
-                                        DBUS_TYPE_OBJECT_PATH, &c_app_path,
-                                        DBUS_TYPE_STRING, &c_config,
-                                        DBUS_TYPE_INVALID);
-
-
-        env->ReleaseStringUTFChars(devicePath, c_device_path);
-        env->ReleaseStringUTFChars(appPath, c_app_path);
-        env->ReleaseStringUTFChars(config, c_config);
-
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath,
-                                     jstring channelPath, jint code) {
-    ALOGE("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        int *data = (int *) malloc(sizeof(int));
-        if (data == NULL) return JNI_FALSE;
-
-        *data = code;
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
-                                        data, eventLoopNat, c_device_path,
-                                        DBUS_HEALTH_DEVICE_IFACE, "DestroyChannel",
-                                        DBUS_TYPE_OBJECT_PATH, &c_channel_path,
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(devicePath, c_device_path);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) {
-    ALOGE("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           c_device_path,
-                           DBUS_HEALTH_DEVICE_IFACE, "GetProperties",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(devicePath, c_device_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            DBusMessageIter iter;
-            jobjectArray str_array = NULL;
-            if (dbus_message_iter_init(reply, &iter))
-                str_array = parse_health_device_properties(env, &iter);
-            dbus_message_unref(reply);
-            jstring path = (jstring) env->GetObjectArrayElement(str_array, 1);
-
-            return path;
-        }
-    }
-#endif
-    return NULL;
-}
-
-static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring channelPath) {
-    ALOGE("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                                            c_channel_path,
-                                            DBUS_HEALTH_CHANNEL_IFACE, "GetProperties",
-                                            DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            DBusMessageIter iter;
-            jobjectArray str_array = NULL;
-            if (dbus_message_iter_init(reply, &iter))
-                str_array = parse_health_channel_properties(env, &iter);
-            dbus_message_unref(reply);
-
-            jint len = env->GetArrayLength(str_array);
-
-            jstring name, path;
-            const char *c_name;
-
-            for (int i = 0; i < len; i+=2) {
-                name = (jstring) env->GetObjectArrayElement(str_array, i);
-                c_name = env->GetStringUTFChars(name, NULL);
-
-                if (!strcmp(c_name, "Application")) {
-                    path = (jstring) env->GetObjectArrayElement(str_array, i+1);
-                    env->ReleaseStringUTFChars(name, c_name);
-                    return path;
-                }
-                env->ReleaseStringUTFChars(name, c_name);
-            }
-        }
-    }
-#endif
-    return NULL;
-}
-
-static jboolean releaseChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                                            c_channel_path,
-                                            DBUS_HEALTH_CHANNEL_IFACE, "Release",
-                                            DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        int32_t fd;
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                                            c_channel_path,
-                                            DBUS_HEALTH_CHANNEL_IFACE, "Acquire",
-                                            DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-            return NULL;
-        }
-
-        fd = dbus_returns_unixfd(env, reply);
-        if (fd == -1) return NULL;
-
-        int flags = fcntl(fd, F_GETFL);
-        if (flags < 0) {
-           ALOGE("Can't get flags with fcntl(): %s (%d)",
-                                strerror(errno), errno);
-           releaseChannelFdNative(env, object, channelPath);
-           close(fd);
-           return NULL;
-        }
-
-        flags &= ~O_NONBLOCK;
-        int status = fcntl(fd, F_SETFL, flags);
-        if (status < 0) {
-           ALOGE("Can't set flags with fcntl(): %s (%d)",
-               strerror(errno), errno);
-           releaseChannelFdNative(env, object, channelPath);
-           close(fd);
-           return NULL;
-        }
-
-        // Create FileDescriptor object
-        jobject fileDesc = jniCreateFileDescriptor(env, fd);
-        if (fileDesc == NULL) {
-            // FileDescriptor constructor has thrown an exception
-            releaseChannelFdNative(env, object, channelPath);
-            close(fd);
-            return NULL;
-        }
-
-        // Wrap it in a ParcelFileDescriptor
-        jobject parcelFileDesc = newParcelFileDescriptor(env, fileDesc);
-        if (parcelFileDesc == NULL) {
-            // ParcelFileDescriptor constructor has thrown an exception
-            releaseChannelFdNative(env, object, channelPath);
-            close(fd);
-            return NULL;
-        }
-
-        return parcelFileDesc;
-    }
-#endif
-    return NULL;
-}
-
-
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-    {"classInitNative", "()V", (void*)classInitNative},
-    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
-    {"setupNativeDataNative", "()Z", (void *)setupNativeDataNative},
-    {"tearDownNativeDataNative", "()Z", (void *)tearDownNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"getAdapterPathNative", "()Ljava/lang/String;", (void*)getAdapterPathNative},
-
-    {"isEnabledNative", "()I", (void *)isEnabledNative},
-    {"enableNative", "()I", (void *)enableNative},
-    {"disableNative", "()I", (void *)disableNative},
-
-    {"getAdapterPropertiesNative", "()[Ljava/lang/Object;", (void *)getAdapterPropertiesNative},
-    {"getDevicePropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
-      (void *)getDevicePropertiesNative},
-    {"setAdapterPropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
-      (void *)setAdapterPropertyStringNative},
-    {"setAdapterPropertyBooleanNative", "(Ljava/lang/String;I)Z",
-      (void *)setAdapterPropertyBooleanNative},
-    {"setAdapterPropertyIntegerNative", "(Ljava/lang/String;I)Z",
-      (void *)setAdapterPropertyIntegerNative},
-
-    {"startDiscoveryNative", "()Z", (void*)startDiscoveryNative},
-    {"stopDiscoveryNative", "()Z", (void *)stopDiscoveryNative},
-
-    {"readAdapterOutOfBandDataNative", "()[B", (void *)readAdapterOutOfBandDataNative},
-    {"createPairedDeviceNative", "(Ljava/lang/String;I)Z", (void *)createPairedDeviceNative},
-    {"createPairedDeviceOutOfBandNative", "(Ljava/lang/String;I)Z",
-                                    (void *)createPairedDeviceOutOfBandNative},
-    {"cancelDeviceCreationNative", "(Ljava/lang/String;)Z", (void *)cancelDeviceCreationNative},
-    {"removeDeviceNative", "(Ljava/lang/String;)Z", (void *)removeDeviceNative},
-    {"getDeviceServiceChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)I",
-      (void *)getDeviceServiceChannelNative},
-
-    {"setPairingConfirmationNative", "(Ljava/lang/String;ZI)Z",
-            (void *)setPairingConfirmationNative},
-    {"setPasskeyNative", "(Ljava/lang/String;II)Z", (void *)setPasskeyNative},
-    {"setRemoteOutOfBandDataNative", "(Ljava/lang/String;[B[BI)Z", (void *)setRemoteOutOfBandDataNative},
-    {"setAuthorizationNative", "(Ljava/lang/String;ZI)Z", (void *)setAuthorizationNative},
-    {"setPinNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)setPinNative},
-    {"cancelPairingUserInputNative", "(Ljava/lang/String;I)Z",
-            (void *)cancelPairingUserInputNative},
-    {"setDevicePropertyBooleanNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
-            (void *)setDevicePropertyBooleanNative},
-    {"setDevicePropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
-            (void *)setDevicePropertyStringNative},
-    {"createDeviceNative", "(Ljava/lang/String;)Z", (void *)createDeviceNative},
-    {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative},
-    {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative},
-    {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative},
-    {"addReservedServiceRecordsNative", "([I)[I", (void *) addReservedServiceRecordsNative},
-    {"removeReservedServiceRecordsNative", "([I)Z", (void *) removeReservedServiceRecordsNative},
-    {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative},
-    // HID functions
-    {"connectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)connectInputDeviceNative},
-    {"disconnectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectInputDeviceNative},
-
-    {"setBluetoothTetheringNative", "(ZLjava/lang/String;Ljava/lang/String;)Z",
-              (void *)setBluetoothTetheringNative},
-    {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
-              (void *)connectPanDeviceNative},
-    {"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative},
-    {"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
-              (void *)disconnectPanServerDeviceNative},
-    // Health function
-    {"registerHealthApplicationNative",
-              "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
-              (void *)registerHealthApplicationNative},
-    {"registerHealthApplicationNative",
-            "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
-            (void *)registerSinkHealthApplicationNative},
-
-    {"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z",
-              (void *)unregisterHealthApplicationNative},
-    {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z",
-              (void *)createChannelNative},
-    {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
-              (void *)destroyChannelNative},
-    {"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative},
-    {"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;",
-              (void *)getChannelApplicationNative},
-    {"getChannelFdNative", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", (void *)getChannelFdNative},
-    {"releaseChannelFdNative", "(Ljava/lang/String;)Z", (void *)releaseChannelFdNative},
-};
-
-
-int register_android_server_BluetoothService(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/server/BluetoothService", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index dacbe41..8b85a7b7 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -157,6 +157,7 @@
         return false;
     }
 
+    bool ret = false;
     for (int i = start; i < start + count; i++) {
         // XXX this thinks it knows that surrogates are never mirrored
 
@@ -165,10 +166,10 @@
 
         if (c1 != c2) {
             data[i] = c2;
-            return true;
+            ret = true;
         }
     }
-    return false;
+    return ret;
 }
 
 static jchar getMirror(JNIEnv* env, jobject obj, jchar c)
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index a51b77e..ade3180 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -528,8 +528,11 @@
     }
     const jchar* glyphs = value->getGlyphs();
     size_t glyphsCount = value->getGlyphsCount();
+    jfloat totalAdvance = value->getTotalAdvance();
+    const float* positions = value->getPos();
     int bytesCount = glyphsCount * sizeof(jchar);
-    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
+    renderer->drawGeneralText((const char*) glyphs, bytesCount, glyphsCount, x, y,
+            positions, paint, totalAdvance);
 }
 
 static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
@@ -556,8 +559,11 @@
     }
     const jchar* glyphs = value->getGlyphs();
     size_t glyphsCount = value->getGlyphsCount();
+    jfloat totalAdvance = value->getTotalAdvance();
+    const float* positions = value->getPos();
     int bytesCount = glyphsCount * sizeof(jchar);
-    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
+    renderer->drawGeneralText((const char*) glyphs, bytesCount, glyphsCount, x, y,
+            positions, paint, totalAdvance);
 }
 
 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
@@ -769,6 +775,13 @@
     env->ReleaseIntArrayElements(layerInfo, storage, 0);
 }
 
+static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz,
+        Layer* layer, jboolean isOpaque) {
+    if (layer) {
+        layer->setBlend(!isOpaque);
+    }
+}
+
 static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
         Layer* layer, jint width, jint height, jboolean isOpaque, jobject surface) {
     float transform[16];
@@ -803,10 +816,6 @@
     LayerRenderer::destroyLayerDeferred(layer);
 }
 
-static void android_view_GLES20Canvas_flushLayer(JNIEnv* env, jobject clazz, Layer* layer) {
-    LayerRenderer::flushLayer(layer);
-}
-
 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
     renderer->drawLayer(layer, x, y, paint);
@@ -969,13 +978,13 @@
     { "nCreateLayerRenderer",    "(I)I",       (void*) android_view_GLES20Canvas_createLayerRenderer },
     { "nCreateLayer",            "(IIZ[I)I",   (void*) android_view_GLES20Canvas_createLayer },
     { "nResizeLayer",            "(III[I)V" ,  (void*) android_view_GLES20Canvas_resizeLayer },
+    { "nSetOpaqueLayer",         "(IZ)V",      (void*) android_view_GLES20Canvas_setOpaqueLayer },
     { "nCreateTextureLayer",     "(Z[I)I",     (void*) android_view_GLES20Canvas_createTextureLayer },
     { "nUpdateTextureLayer",     "(IIIZLandroid/graphics/SurfaceTexture;)V",
             (void*) android_view_GLES20Canvas_updateTextureLayer },
     { "nUpdateRenderLayer",      "(IIIIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
     { "nDestroyLayer",           "(I)V",       (void*) android_view_GLES20Canvas_destroyLayer },
     { "nDestroyLayerDeferred",   "(I)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
-    { "nFlushLayer",             "(I)V",       (void*) android_view_GLES20Canvas_flushLayer },
     { "nDrawLayer",              "(IIFFI)V",   (void*) android_view_GLES20Canvas_drawLayer },
     { "nCopyLayer",              "(II)Z",      (void*) android_view_GLES20Canvas_copyLayer },
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 5739cbe..60f8c48 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -481,24 +481,6 @@
     }
 }
 
-static void Surface_freezeDisplay(
-        JNIEnv* env, jobject clazz, jint display)
-{
-    int err = SurfaceComposerClient::freezeDisplay(display, 0);
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_unfreezeDisplay(
-        JNIEnv* env, jobject clazz, jint display)
-{
-    int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
-
 class ScreenshotPixelRef : public SkPixelRef {
 public:
     ScreenshotPixelRef(SkColorTable* ctable) {
@@ -655,28 +637,6 @@
     }
 }
 
-static void Surface_freeze(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->freeze();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_unfreeze(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->unfreeze();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
 static void Surface_setFlags(
         JNIEnv* env, jobject clazz, jint flags, jint mask)
 {
@@ -735,18 +695,6 @@
     }
 }
 
-static void Surface_setFreezeTint(
-        JNIEnv* env, jobject clazz,
-        jint tint)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->setFreezeTint(tint);
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
 static void Surface_setWindowCrop(JNIEnv* env, jobject thiz, jobject crop)
 {
     const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz));
@@ -892,8 +840,6 @@
     {"openTransaction",     "()V",  (void*)Surface_openTransaction },
     {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
     {"setOrientation",      "(III)V", (void*)Surface_setOrientation },
-    {"freezeDisplay",       "(I)V", (void*)Surface_freezeDisplay },
-    {"unfreezeDisplay",     "(I)V", (void*)Surface_unfreezeDisplay },
     {"screenshot",          "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
     {"screenshot",          "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
     {"setLayer",            "(I)V", (void*)Surface_setLayer },
@@ -901,13 +847,10 @@
     {"setSize",             "(II)V",(void*)Surface_setSize },
     {"hide",                "()V",  (void*)Surface_hide },
     {"show",                "()V",  (void*)Surface_show },
-    {"freeze",              "()V",  (void*)Surface_freeze },
-    {"unfreeze",            "()V",  (void*)Surface_unfreeze },
     {"setFlags",            "(II)V",(void*)Surface_setFlags },
     {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
     {"setAlpha",            "(F)V", (void*)Surface_setAlpha },
     {"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
-    {"setFreezeTint",       "(I)V",  (void*)Surface_setFreezeTint },
     {"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
     {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
     {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind },
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 8777131..3f9942e 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -114,14 +114,12 @@
 }
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -139,11 +137,10 @@
     if (*array == NULL) {
         return (void*) NULL;
     }
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 static void
@@ -181,10 +178,12 @@
         if (allowIndirectBuffers(_env)) {
             jarray array = 0;
             jint remaining;
-            buf = getPointer(_env, buffer, &array, &remaining);
+            jint offset;
+            buf = getPointer(_env, buffer, &array, &remaining, &offset);
             if (array) {
                 releasePointer(_env, array, buf, 0);
             }
+            buf = buf + offset;
         } else {
             jniThrowException(_env, "java/lang/IllegalArgumentException",
                               "Must use a native order direct Buffer");
@@ -418,6 +417,7 @@
 android_glColorPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -441,10 +441,15 @@
 android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexImage2D(
         (GLenum)target,
         (GLint)level,
@@ -465,10 +470,15 @@
 android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexSubImage2D(
         (GLenum)target,
         (GLint)level,
@@ -530,21 +540,30 @@
 static void
 android_glDeleteTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -561,21 +580,34 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
 static void
 android_glDeleteTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glDeleteTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -585,6 +617,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDepthFunc ( GLenum func ) */
@@ -658,15 +693,25 @@
 static void
 android_glDrawElements__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *indices = (GLvoid *) 0;
 
-    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < count) {
-        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count < needed";
         goto exit;
     }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (GLvoid *) (_indicesBase + _bufferOffset);
+    }
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
@@ -678,6 +723,9 @@
     if (_array) {
         releasePointer(_env, _array, indices, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEnable ( GLenum cap ) */
@@ -726,16 +774,23 @@
 static void
 android_glFogfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -765,7 +820,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -782,17 +839,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glFogfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -819,9 +883,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glFogfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -831,6 +901,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogx ( GLenum pname, GLfixed param ) */
@@ -847,16 +920,23 @@
 static void
 android_glFogxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -886,7 +966,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -903,17 +985,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glFogxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -940,9 +1029,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glFogxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -952,6 +1047,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFrontFace ( GLenum mode ) */
@@ -996,24 +1094,29 @@
 android_glGenTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -1030,6 +1133,9 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenTextures ( GLsizei n, GLuint *textures ) */
@@ -1037,16 +1143,24 @@
 android_glGenTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glGenTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -1056,6 +1170,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glGetError ( void ) */
@@ -1072,18 +1189,22 @@
 android_glGetIntegerv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1420,7 +1541,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1437,6 +1559,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetIntegerv ( GLenum pname, GLint *params ) */
@@ -1444,11 +1569,14 @@
 android_glGetIntegerv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_ALPHA_BITS)
@@ -1782,9 +1910,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetIntegerv(
         (GLenum)pname,
         (GLint *)params
@@ -1794,6 +1927,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* const GLubyte * glGetString ( GLenum name ) */
@@ -1825,16 +1961,23 @@
 static void
 android_glLightModelfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1855,7 +1998,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1872,17 +2017,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glLightModelfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -1900,9 +2052,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightModelfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -1912,6 +2070,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelx ( GLenum pname, GLfixed param ) */
@@ -1928,16 +2089,23 @@
 static void
 android_glLightModelxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1958,7 +2126,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1975,17 +2145,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glLightModelxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -2003,9 +2180,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightModelxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -2015,6 +2198,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightf ( GLenum light, GLenum pname, GLfloat param ) */
@@ -2032,16 +2218,23 @@
 static void
 android_glLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2088,7 +2281,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2106,17 +2301,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) */
 static void
 android_glLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2160,9 +2362,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -2173,6 +2381,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightx ( GLenum light, GLenum pname, GLfixed param ) */
@@ -2190,16 +2401,23 @@
 static void
 android_glLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2246,7 +2464,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2264,17 +2484,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) */
 static void
 android_glLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2318,9 +2545,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -2331,6 +2564,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLineWidth ( GLfloat width ) */
@@ -2362,16 +2598,23 @@
 static void
 android_glLoadMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2388,6 +2631,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixf ( const GLfloat *m ) */
@@ -2395,10 +2641,15 @@
 android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixf(
         (GLfloat *)m
     );
@@ -2411,16 +2662,23 @@
 static void
 android_glLoadMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2437,6 +2695,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2444,10 +2705,15 @@
 android_glLoadMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixx(
         (GLfixed *)m
     );
@@ -2480,16 +2746,23 @@
 static void
 android_glMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2522,7 +2795,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2540,17 +2815,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) */
 static void
 android_glMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2580,9 +2862,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -2593,6 +2881,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialx ( GLenum face, GLenum pname, GLfixed param ) */
@@ -2610,16 +2901,23 @@
 static void
 android_glMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2652,7 +2950,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2670,17 +2970,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) */
 static void
 android_glMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2710,9 +3017,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -2723,6 +3036,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMatrixMode ( GLenum mode ) */
@@ -2738,16 +3054,23 @@
 static void
 android_glMultMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2764,6 +3087,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixf ( const GLfloat *m ) */
@@ -2771,10 +3097,15 @@
 android_glMultMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glMultMatrixf(
         (GLfloat *)m
     );
@@ -2787,16 +3118,23 @@
 static void
 android_glMultMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2813,6 +3151,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixx ( const GLfixed *m ) */
@@ -2820,10 +3161,15 @@
 android_glMultMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glMultMatrixx(
         (GLfixed *)m
     );
@@ -2885,6 +3231,7 @@
 android_glNormalPointerBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2996,12 +3343,16 @@
 static void
 android_glReadPixels__IIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
-    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    if (pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
+    }
     glReadPixels(
         (GLint)x,
         (GLint)y,
@@ -3012,7 +3363,7 @@
         (GLvoid *)pixels
     );
     if (_array) {
-        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, pixels, JNI_TRUE);
     }
 }
 
@@ -3139,6 +3490,7 @@
 android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -3172,16 +3524,23 @@
 static void
 android_glTexEnvfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3208,7 +3567,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3226,17 +3587,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexEnvfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3260,9 +3628,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvfv(
         (GLenum)target,
         (GLenum)pname,
@@ -3273,6 +3647,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvx ( GLenum target, GLenum pname, GLfixed param ) */
@@ -3290,16 +3667,23 @@
 static void
 android_glTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3326,7 +3710,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -3344,17 +3730,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3378,9 +3771,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvxv(
         (GLenum)target,
         (GLenum)pname,
@@ -3391,6 +3790,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) */
@@ -3398,11 +3800,16 @@
 android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexImage2D(
         (GLenum)target,
@@ -3447,11 +3854,16 @@
 android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexSubImage2D(
         (GLenum)target,
@@ -3496,6 +3908,7 @@
 android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -3531,6 +3944,8 @@
 android_glQueryMatrixxOES___3II_3II
   (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLbitfield _returnValue = -1;
     GLfixed *mantissa_base = (GLfixed *) 0;
     jint _mantissaRemaining;
@@ -3541,18 +3956,21 @@
 
     if (!mantissa_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissa == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissa == null";
         goto exit;
     }
     if (mantissaOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissaOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissaOffset < 0";
         goto exit;
     }
     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - mantissaOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - mantissaOffset < 16 < needed";
         goto exit;
     }
     mantissa_base = (GLfixed *)
@@ -3561,18 +3979,21 @@
 
     if (!exponent_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponent == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponent == null";
         goto exit;
     }
     if (exponentOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponentOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponentOffset < 0";
         goto exit;
     }
     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - exponentOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - exponentOffset < 16 < needed";
         goto exit;
     }
     exponent_base = (GLint *)
@@ -3593,6 +4014,9 @@
         _env->ReleasePrimitiveArrayCritical(mantissa_ref, mantissa_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -3601,37 +4025,54 @@
 android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _mantissaArray = (jarray) 0;
+    jint _mantissaBufferOffset = (jint) 0;
     jarray _exponentArray = (jarray) 0;
+    jint _exponentBufferOffset = (jint) 0;
     GLbitfield _returnValue = -1;
     jint _mantissaRemaining;
     GLfixed *mantissa = (GLfixed *) 0;
     jint _exponentRemaining;
     GLint *exponent = (GLint *) 0;
 
-    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
+    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
-    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
+    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
+    if (mantissa == NULL) {
+        char * _mantissaBase = (char *)_env->GetPrimitiveArrayCritical(_mantissaArray, (jboolean *) 0);
+        mantissa = (GLfixed *) (_mantissaBase + _mantissaBufferOffset);
+    }
+    if (exponent == NULL) {
+        char * _exponentBase = (char *)_env->GetPrimitiveArrayCritical(_exponentArray, (jboolean *) 0);
+        exponent = (GLint *) (_exponentBase + _exponentBufferOffset);
+    }
     _returnValue = glQueryMatrixxOES(
         (GLfixed *)mantissa,
         (GLint *)exponent
     );
 
 exit:
-    if (_mantissaArray) {
-        releasePointer(_env, _mantissaArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_exponentArray) {
-        releasePointer(_env, _exponentArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _exponentArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_mantissaArray) {
+        releasePointer(_env, _mantissaArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
     }
     return _returnValue;
 }
@@ -3650,17 +4091,27 @@
 static void
 android_glBufferData__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
     if (data_buf) {
-        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
         if (_remaining < size) {
-            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "remaining() < size < needed";
             goto exit;
         }
     }
+    if (data_buf && data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferData(
         (GLenum)target,
         (GLsizeiptr)size,
@@ -3672,21 +4123,34 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
 static void
 android_glBufferSubData__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < size) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < size < needed";
         goto exit;
     }
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferSubData(
         (GLenum)target,
         (GLintptr)offset,
@@ -3698,27 +4162,39 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *equation_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     equation_base = (GLfloat *)
@@ -3735,21 +4211,34 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
-    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfloat *) (_equationBase + _bufferOffset);
+    }
     glClipPlanef(
         (GLenum)plane,
         (GLfloat *)equation
@@ -3759,27 +4248,39 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *equation_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     equation_base = (GLfixed *)
@@ -3796,21 +4297,34 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
-    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfixed *) (_equationBase + _bufferOffset);
+    }
     glClipPlanex(
         (GLenum)plane,
         (GLfixed *)equation
@@ -3820,6 +4334,9 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) */
@@ -3850,21 +4367,30 @@
 static void
 android_glDeleteBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -3881,21 +4407,34 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
 static void
 android_glDeleteBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glDeleteBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -3905,18 +4444,27 @@
     if (_array) {
         releasePointer(_env, _array, buffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset ) */
 static void
 android_glDrawElements__IIII
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
         (const GLvoid *)offset
     );
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -3924,24 +4472,29 @@
 android_glGenBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -3958,6 +4511,9 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -3965,16 +4521,24 @@
 android_glGenBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glGenBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -3984,6 +4548,9 @@
     if (_array) {
         releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
@@ -3991,18 +4558,22 @@
 android_glGetBooleanv__I_3ZI
   (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLboolean *params_base = (GLboolean *) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4020,24 +4591,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
 static void
 android_glGetBooleanv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
-    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLboolean *) (_paramsBase + _bufferOffset);
+    }
     glGetBooleanv(
         (GLenum)pname,
         (GLboolean *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -4062,18 +4640,22 @@
 android_glGetClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *eqn_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -4091,24 +4673,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
 static void
 android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
-    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfloat *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanef(
         (GLenum)pname,
         (GLfloat *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -4117,18 +4706,22 @@
 android_glGetClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *eqn_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -4146,24 +4739,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) */
 static void
 android_glGetClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
-    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfixed *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanex(
         (GLenum)pname,
         (GLfixed *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -4172,18 +4772,22 @@
 android_glGetFixedv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4201,24 +4805,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedv ( GLenum pname, GLfixed *params ) */
 static void
 android_glGetFixedv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetFixedv(
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -4227,18 +4838,22 @@
 android_glGetFloatv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4256,24 +4871,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFloatv ( GLenum pname, GLfloat *params ) */
 static void
 android_glGetFloatv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetFloatv(
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -4282,18 +4904,22 @@
 android_glGetLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4341,7 +4967,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -4359,6 +4986,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) */
@@ -4366,11 +4996,14 @@
 android_glGetLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -4415,9 +5048,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -4428,6 +5066,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -4435,18 +5076,22 @@
 android_glGetLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4494,7 +5139,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -4512,6 +5158,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -4519,11 +5168,14 @@
 android_glGetLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -4568,9 +5220,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -4581,6 +5238,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -4588,18 +5248,22 @@
 android_glGetMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4633,7 +5297,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -4651,6 +5316,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -4658,11 +5326,14 @@
 android_glGetMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -4693,9 +5364,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -4706,6 +5382,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -4713,18 +5392,22 @@
 android_glGetMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4758,7 +5441,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -4776,6 +5460,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -4783,11 +5470,14 @@
 android_glGetMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -4818,9 +5508,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -4831,6 +5526,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -4838,18 +5536,22 @@
 android_glGetTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4877,7 +5579,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -4895,6 +5598,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -4902,11 +5608,14 @@
 android_glGetTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -4931,9 +5640,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnviv(
         (GLenum)env,
         (GLenum)pname,
@@ -4944,6 +5658,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -4951,18 +5668,22 @@
 android_glGetTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4990,7 +5711,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5008,6 +5730,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -5015,11 +5740,14 @@
 android_glGetTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -5044,9 +5772,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvxv(
         (GLenum)env,
         (GLenum)pname,
@@ -5057,6 +5790,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -5064,24 +5800,29 @@
 android_glGetTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5099,6 +5840,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -5106,16 +5850,24 @@
 android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -5126,6 +5878,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -5133,24 +5888,29 @@
 android_glGetTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -5168,6 +5928,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -5175,16 +5938,24 @@
 android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -5195,6 +5966,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -5202,24 +5976,29 @@
 android_glGetTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5237,6 +6016,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -5244,16 +6026,24 @@
 android_glGetTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -5264,6 +6054,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLboolean glIsBuffer ( GLuint buffer ) */
@@ -5324,21 +6117,30 @@
 static void
 android_glPointParameterfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5355,21 +6157,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glPointParameterfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -5379,6 +6194,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterx ( GLenum pname, GLfixed param ) */
@@ -5395,21 +6213,30 @@
 static void
 android_glPointParameterxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5426,21 +6253,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glPointParameterxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -5450,6 +6290,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer ) */
@@ -5457,6 +6300,7 @@
 android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -5501,16 +6345,23 @@
 static void
 android_glTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -5537,7 +6388,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -5555,17 +6408,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -5589,9 +6449,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexEnviv(
         (GLenum)target,
         (GLenum)pname,
@@ -5602,27 +6468,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5640,21 +6518,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -5665,6 +6556,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
@@ -5682,21 +6576,30 @@
 static void
 android_glTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -5714,21 +6617,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -5739,27 +6655,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5777,21 +6705,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -5802,6 +6743,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -5842,21 +6786,30 @@
 static void
 android_glDrawTexfvOES___3FI
   (JNIEnv *_env, jobject _this, jfloatArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *coords_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfloat *)
@@ -5872,21 +6825,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexfvOES ( const GLfloat *coords ) */
 static void
 android_glDrawTexfvOES__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
-    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfloat *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexfvOES(
         (GLfloat *)coords
     );
@@ -5895,6 +6861,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height ) */
@@ -5914,21 +6883,30 @@
 static void
 android_glDrawTexivOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *coords_base = (GLint *) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLint *)
@@ -5944,21 +6922,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexivOES ( const GLint *coords ) */
 static void
 android_glDrawTexivOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
-    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLint *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexivOES(
         (GLint *)coords
     );
@@ -5967,6 +6958,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height ) */
@@ -5986,21 +6980,30 @@
 static void
 android_glDrawTexsvOES___3SI
   (JNIEnv *_env, jobject _this, jshortArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLshort *coords_base = (GLshort *) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLshort *)
@@ -6016,21 +7019,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexsvOES ( const GLshort *coords ) */
 static void
 android_glDrawTexsvOES__Ljava_nio_ShortBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
-    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLshort *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexsvOES(
         (GLshort *)coords
     );
@@ -6039,6 +7055,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height ) */
@@ -6058,21 +7077,30 @@
 static void
 android_glDrawTexxvOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *coords_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfixed *)
@@ -6088,21 +7116,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxvOES ( const GLfixed *coords ) */
 static void
 android_glDrawTexxvOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
-    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfixed *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexxvOES(
         (GLfixed *)coords
     );
@@ -6111,6 +7152,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadPaletteFromModelViewMatrixOES ( void ) */
@@ -6125,6 +7169,7 @@
 android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -6160,6 +7205,7 @@
 android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -6273,7 +7319,7 @@
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
         jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glCheckFramebufferStatusOES");
-            return 0;
+    return 0;
     }
     GLint _returnValue = 0;
     _returnValue = glCheckFramebufferStatusOES(
@@ -6292,24 +7338,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -6326,6 +7377,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers ) */
@@ -6338,16 +7392,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glDeleteFramebuffersOES(
         (GLint)n,
         (GLuint *)framebuffers
@@ -6357,6 +7419,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6369,24 +7434,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -6403,6 +7473,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6415,16 +7488,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glDeleteRenderbuffersOES(
         (GLint)n,
         (GLuint *)renderbuffers
@@ -6434,6 +7515,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer ) */
@@ -6495,24 +7579,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -6529,6 +7618,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffersOES ( GLint n, GLuint *framebuffers ) */
@@ -6541,16 +7633,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glGenFramebuffersOES(
         (GLint)n,
         (GLuint *)framebuffers
@@ -6560,6 +7660,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6572,24 +7675,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -6606,6 +7714,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6618,16 +7729,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glGenRenderbuffersOES(
         (GLint)n,
         (GLuint *)renderbuffers
@@ -6637,6 +7756,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
@@ -6649,18 +7771,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6680,6 +7806,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
@@ -6691,12 +7820,16 @@
             "glGetFramebufferAttachmentParameterivOES");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetFramebufferAttachmentParameterivOES(
         (GLint)target,
         (GLint)attachment,
@@ -6704,7 +7837,7 @@
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6718,18 +7851,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6748,6 +7885,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) */
@@ -6759,19 +7899,23 @@
             "glGetRenderbufferParameterivOES");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetRenderbufferParameterivOES(
         (GLint)target,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6785,18 +7929,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6815,6 +7963,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
@@ -6826,19 +7977,23 @@
             "glGetTexGenfv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenfv(
         (GLint)coord,
         (GLint)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6852,18 +8007,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6882,6 +8041,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) */
@@ -6893,19 +8055,23 @@
             "glGetTexGeniv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGeniv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6919,18 +8085,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6949,6 +8119,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) */
@@ -6960,19 +8133,23 @@
             "glGetTexGenxv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenxv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6983,7 +8160,7 @@
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
         jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glIsFramebufferOES");
-            return JNI_FALSE;
+    return JNI_FALSE;
     }
     GLboolean _returnValue = JNI_FALSE;
     _returnValue = glIsFramebufferOES(
@@ -6999,7 +8176,7 @@
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
         jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glIsRenderbufferOES");
-            return JNI_FALSE;
+    return JNI_FALSE;
     }
     GLboolean _returnValue = JNI_FALSE;
     _returnValue = glIsRenderbufferOES(
@@ -7051,18 +8228,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7081,6 +8262,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
@@ -7092,19 +8276,23 @@
             "glTexGenfv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexGenfv(
         (GLint)coord,
         (GLint)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -7134,18 +8322,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7164,6 +8356,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGeniv ( GLint coord, GLint pname, GLint *params ) */
@@ -7175,19 +8370,23 @@
             "glTexGeniv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexGeniv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -7217,18 +8416,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7247,6 +8450,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenxv ( GLint coord, GLint pname, GLint *params ) */
@@ -7258,19 +8464,23 @@
             "glTexGenxv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexGenxv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6546fed..9253f24 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -121,6 +121,7 @@
 
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
+    <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" />
 
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
@@ -508,6 +509,11 @@
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="signature|system" />
 
+    <!-- @hide -->
+    <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="signature|system" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
     <!-- ================================== -->
@@ -1223,6 +1229,19 @@
         android:description="@string/permdesc_injectEvents"
         android:protectionLevel="signature" />
 
+    <!-- @hide Allows an application to register an input filter which filters the stream
+         of user events (keys, touch, trackball) before they are dispatched to any window. -->
+    <permission android:name="android.permission.FILTER_EVENTS"
+        android:label="@string/permlab_filter_events"
+        android:description="@string/permdesc_filter_events"
+        android:protectionLevel="signature" />
+
+    <!-- @hide Allows an application to retrieve info for a window from the window manager. -->
+    <permission android:name="android.permission.RETRIEVE_WINDOW_INFO"
+        android:label="@string/permlab_retrieve_window_info"
+        android:description="@string/permdesc_retrieve_window_info"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
          (usually the monkey command). -->
@@ -1396,6 +1415,11 @@
         android:description="@string/permdesc_devicePower"
         android:protectionLevel="signature" />
 
+   <!-- Allows low-level access to tun tap driver -->
+    <permission android:name="android.permission.NET_TUNNELING"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature" />
+
     <!-- Run as a manufacturer test application, running as the root user.
          Only available when the device is running in manufacturer test mode. -->
     <permission android:name="android.permission.FACTORY_TEST"
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index bc718b5..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index 0892c31..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index 04cc0a2..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index bb553b1..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_suggestions_add.png b/core/res/res/drawable-hdpi/ic_suggestions_add.png
deleted file mode 100644
index 919872c..0000000
--- a/core/res/res/drawable-hdpi/ic_suggestions_add.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_suggestions_delete.png b/core/res/res/drawable-hdpi/ic_suggestions_delete.png
deleted file mode 100644
index fa42db0..0000000
--- a/core/res/res/drawable-hdpi/ic_suggestions_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index 308fe8a..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index 9a25634..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index 77240d0..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index e0b0134..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_suggestions_add.png b/core/res/res/drawable-mdpi/ic_suggestions_add.png
deleted file mode 100644
index e98bdf8..0000000
--- a/core/res/res/drawable-mdpi/ic_suggestions_add.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_suggestions_delete.png b/core/res/res/drawable-mdpi/ic_suggestions_delete.png
deleted file mode 100644
index 78e6ec1..0000000
--- a/core/res/res/drawable-mdpi/ic_suggestions_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index b8e5733..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index ce5da43..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index c16f143..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index 9bed39a..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_add.png b/core/res/res/drawable-xhdpi/ic_suggestions_add.png
deleted file mode 100644
index b1edef7..0000000
--- a/core/res/res/drawable-xhdpi/ic_suggestions_add.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_delete.png b/core/res/res/drawable-xhdpi/ic_suggestions_delete.png
deleted file mode 100644
index 6b1f447..0000000
--- a/core/res/res/drawable-xhdpi/ic_suggestions_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout-land/ssl_certificate.xml b/core/res/res/layout-land/ssl_certificate.xml
index 4f8bd8e..c6c8dd4 100644
--- a/core/res/res/layout-land/ssl_certificate.xml
+++ b/core/res/res/layout-land/ssl_certificate.xml
@@ -23,7 +23,7 @@
         android:id="@+id/body"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:gravity="start"
         android:orientation="vertical" >
 
         <!-- Placeholder for the success message or one or more warnings -->
@@ -43,8 +43,8 @@
             android:scaleType="fitXY"
             android:layout_weight="1"
             android:gravity="fill_horizontal"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"/>
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"/>
 
         <TableLayout
             android:layout_width="match_parent"
@@ -60,8 +60,8 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- Common name: -->
@@ -69,12 +69,12 @@
                 <TextView
                     android:id="@+id/to_common_header"
                     android:text="@string/common_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/to_common"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -83,12 +83,12 @@
                 <TextView
                     android:id="@+id/to_org_header"
                     android:text="@string/org_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/to_org"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -97,12 +97,12 @@
                 <TextView
                     android:id="@+id/to_org_unit_header"
                     android:text="@string/org_unit"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/to_org_unit"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -111,12 +111,12 @@
                 <TextView
                     android:id="@+id/serial_number_header"
                     android:text="@string/serial_number"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/serial_number"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -128,8 +128,8 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- Common name: -->
@@ -137,12 +137,12 @@
                 <TextView
                     android:id="@+id/by_common_header"
                     android:text="@string/common_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/by_common"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -151,12 +151,12 @@
                 <TextView
                     android:id="@+id/by_org_header"
                     android:text="@string/org_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/by_org"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -165,12 +165,12 @@
                 <TextView
                     android:id="@+id/by_org_unit_header"
                     android:text="@string/org_unit"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/by_org_unit"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -182,8 +182,8 @@
                 android:text="@string/validity_period"
                 android:textStyle="bold"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- Issued On: -->
@@ -193,14 +193,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/issued_on"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/issued_on"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
 
             </TableRow>
@@ -212,14 +212,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/expires_on"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/expires_on"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -231,8 +231,8 @@
                 android:text="@string/fingerprints"
                 android:textStyle="bold"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- SHA-256 fingerprint: -->
@@ -242,14 +242,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/sha256_fingerprint"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/sha256_fingerprint"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
 
             </TableRow>
@@ -261,14 +261,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/sha1_fingerprint"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/sha1_fingerprint"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
 
             </TableRow>
diff --git a/core/res/res/layout-land/usb_storage_activity.xml b/core/res/res/layout-land/usb_storage_activity.xml
index 50ca569..d52f0a5 100644
--- a/core/res/res/layout-land/usb_storage_activity.xml
+++ b/core/res/res/layout-land/usb_storage_activity.xml
@@ -52,16 +52,16 @@
             <Button android:id="@+id/mount_button" 
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
+                android:paddingStart="18dip"
+                android:paddingEnd="18dip"
                 android:text="@string/usb_storage_button_mount"
                 />
             <Button android:id="@+id/unmount_button"
                 android:visibility="gone"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
+                android:paddingStart="18dip"
+                android:paddingEnd="18dip"
                 android:text="@string/usb_storage_stop_button_mount"
                 />
             <ProgressBar android:id="@+id/progress"
diff --git a/core/res/res/layout-large/action_mode_close_item.xml b/core/res/res/layout-large/action_mode_close_item.xml
index f8b397a..df06de6 100644
--- a/core/res/res/layout-large/action_mode_close_item.xml
+++ b/core/res/res/layout-large/action_mode_close_item.xml
@@ -18,11 +18,11 @@
         android:id="@+id/action_mode_close_button"
         android:focusable="true"
         android:clickable="true"
-        android:paddingLeft="8dip"
+        android:paddingStart="8dip"
         style="?android:attr/actionModeCloseButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_marginRight="16dip">
+        android:layout_marginEnd="16dip">
     <ImageView android:layout_width="48dip"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
@@ -31,8 +31,8 @@
     <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_gravity="center"
-              android:layout_marginLeft="4dip"
-              android:layout_marginRight="16dip"
+              android:layout_marginStart="4dip"
+              android:layout_marginEnd="16dip"
               android:textAppearance="?android:attr/textAppearanceSmall"
               android:textColor="?android:attr/actionMenuTextColor"
               android:textSize="12sp"
diff --git a/core/res/res/layout-sw600dp/keyguard.xml b/core/res/res/layout-sw600dp/keyguard.xml
index ca629f8..f8f482d 100644
--- a/core/res/res/layout-sw600dp/keyguard.xml
+++ b/core/res/res/layout-sw600dp/keyguard.xml
@@ -19,9 +19,9 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:paddingLeft="20dip"
+    android:paddingStart="20dip"
     android:paddingTop="20dip"
-    android:paddingRight="20dip"
+    android:paddingEnd="20dip"
     android:paddingBottom="20dip"
     android:orientation="vertical" 
     android:layout_width="wrap_content"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
index 56c832c..a0b1aaa 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
@@ -36,7 +36,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_marginLeft="4dip"
+                android:layout_marginStart="4dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:gravity="center_vertical"
                 android:drawableLeft="@drawable/ic_lock_idle_lock"
@@ -57,7 +57,7 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@+id/spacerTop"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="9dip"
+                android:layout_marginStart="9dip"
                 android:textAppearance="?android:attr/textAppearanceSmall"
                 android:text="@android:string/lockscreen_glogin_instructions"
                 />
@@ -68,8 +68,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/instructions"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:hint="@android:string/lockscreen_glogin_username_hint"
                 android:inputType="textEmailAddress"
                 />
@@ -80,8 +80,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/login"
                 android:layout_marginTop="15dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:inputType="textPassword"
                 android:hint="@android:string/lockscreen_glogin_password_hint"
                 android:nextFocusRight="@+id/ok"
@@ -95,8 +95,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/password"
                 android:layout_marginTop="7dip"
-                android:layout_marginRight="7dip"
-                android:layout_alignParentRight="true"
+                android:layout_marginEnd="7dip"
+                android:layout_alignParentEnd="true"
                 android:text="@android:string/lockscreen_glogin_submit_button"
                 />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_lock.xml b/core/res/res/layout-sw600dp/keyguard_screen_lock.xml
index c7aa654..ea061ff 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_lock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_lock.xml
@@ -33,8 +33,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginBottom="15dip"
-        android:layout_marginLeft="15dip"
-        android:layout_marginRight="15dip"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="15dip"
         android:paddingTop="20dip"
         android:paddingBottom="20dip"
         android:background="@android:drawable/popup_full_dark"
@@ -107,7 +107,7 @@
             <ImageView android:id="@+id/batteryInfoIcon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:gravity="center"
             />
@@ -142,7 +142,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_alarm"
                 android:gravity="center"
@@ -176,7 +176,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_lock"
                 android:gravity="center"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index 8d5d404..4ceb907 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -39,12 +39,12 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
                 android:layout_marginBottom="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -89,7 +89,7 @@
                     android:layout_weight="1"
                     android:gravity="center"
                     android:layout_gravity="center"
-                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+                    android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
                     android:singleLine="true"
                     android:textStyle="normal"
                     android:inputType="textPassword"
@@ -174,7 +174,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index 95c15e5..da627b5 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -38,11 +38,11 @@
             <include layout="@layout/keyguard_screen_status_port"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -93,7 +93,7 @@
                     android:inputType="textPassword"
                     android:gravity="center"
                     android:layout_gravity="center"
-                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+                    android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
                     android:textSize="24sp"
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:background="@null"
@@ -177,7 +177,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
index 0b94fc1..efb9e2a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
@@ -41,7 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_above="@+id/pinDisplayGroup"
         android:layout_marginTop="9dip"
-        android:gravity="left|bottom"
+        android:gravity="start|bottom"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -56,9 +56,9 @@
         android:addStatesFromChildren="true"
         android:gravity="center_vertical"
         android:baselineAligned="false"
-        android:paddingRight="0dip"
-        android:layout_marginRight="30dip"
-        android:layout_marginLeft="30dip"
+        android:paddingEnd="0dip"
+        android:layout_marginEnd="30dip"
+        android:layout_marginStart="30dip"
         android:background="@android:drawable/edit_text"
     >
 
@@ -77,7 +77,7 @@
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_marginTop="2dip"
-             android:layout_marginRight="2dip"
+             android:layout_marginEnd="2dip"
              android:layout_marginBottom="2dip"
              android:gravity="center"
             />
@@ -90,8 +90,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip">
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip">
 
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
@@ -101,7 +101,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="8dip"
@@ -114,7 +114,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginStart="8dip"
             android:textSize="18sp"
         />
     </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
index 1be4462..db84156 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
@@ -51,8 +51,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:gravity="center_vertical"
             android:background="@android:drawable/edit_text">
 
@@ -72,7 +72,7 @@
                 android:src="@android:drawable/ic_input_delete"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="-3dip"
+                android:layout_marginEnd="-3dip"
                 android:layout_marginBottom="-3dip"
             />
         </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
index 4fafc3c..df999f0 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -23,7 +23,7 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="right">
+        android:gravity="end">
 
     <TextView
         android:id="@+id/carrier"
@@ -66,7 +66,7 @@
             android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             android:layout_marginBottom="6dip"
             />
@@ -91,7 +91,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:drawablePadding="4dip"
             android:textSize="16sp"/>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
index dfab3e3..565785b 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -24,7 +24,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="20dip"
-        android:gravity="right"
+        android:gravity="end"
         >
 
     <TextView
@@ -68,7 +68,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_foreground"
             android:layout_marginBottom="6dip"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -92,7 +92,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:drawablePadding="4dip"
             android:textSize="16sp"/>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index af7d011..4f6b62a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -44,10 +44,10 @@
             <include layout="@layout/keyguard_screen_status_port"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -76,7 +76,7 @@
             android:id="@+id/screenLocked"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="24dip"
+            android:layout_marginStart="24dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginTop="12dip"
             android:drawablePadding="4dip"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 2a2dc31..d5201ec 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -42,11 +42,11 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -78,7 +78,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:gravity="center"
             android:layout_marginTop="12dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:layout_alignParentTop="true"
             android:drawablePadding="4dip"/>
 
@@ -87,7 +87,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_rowSpan="7"
-            android:layout_gravity="center_vertical|right"
+            android:layout_gravity="center_vertical|end"
             android:gravity="center"
             android:focusable="true"
 
@@ -110,9 +110,9 @@
             android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginRight="80dip"
+            android:layout_marginEnd="80dip"
             android:layout_marginBottom="80dip"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:layout_alignParentBottom="true"
             android:drawableLeft="@drawable/ic_emergency"
             style="@style/Widget.Button.Transparent"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
index 0153a2e..51b946a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
@@ -43,12 +43,12 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
                 android:layout_marginBottom="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -91,8 +91,8 @@
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 android:layout_below="@id/lockPattern"
-                android:layout_alignLeft="@id/lockPattern"
-                android:layout_alignRight="@id/lockPattern"
+                android:layout_alignStart="@id/lockPattern"
+                android:layout_alignEnd="@id/lockPattern"
                 android:layout_marginTop="28dip"
                 style="?android:attr/buttonBarStyle"
                 android:gravity="center"
@@ -146,7 +146,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
index 7231ead..1d6b6a9 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
@@ -39,11 +39,11 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -85,8 +85,8 @@
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 android:layout_below="@id/lockPattern"
-                android:layout_alignLeft="@id/lockPattern"
-                android:layout_alignRight="@id/lockPattern"
+                android:layout_alignStart="@id/lockPattern"
+                android:layout_alignEnd="@id/lockPattern"
                 style="?android:attr/buttonBarStyle"
                 android:gravity="center"
                 android:weightSum="2">
@@ -139,7 +139,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_transport_control.xml b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
index 86b103e..f864339 100644
--- a/core/res/res/layout-sw600dp/keyguard_transport_control.xml
+++ b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
@@ -48,8 +48,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
             android:gravity="center_horizontal"
             android:singleLine="true"
             android:ellipsize="end"
diff --git a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml
index 269e086..a09ad0c 100644
--- a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml
+++ b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml
@@ -13,7 +13,7 @@
         android:layout_gravity="center_vertical"
         android:layout_weight="1"
         android:orientation="vertical"
-        android:paddingLeft="16dp"
+        android:paddingStart="16dp"
         >
         <TextView android:id="@+id/title"
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
diff --git a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml
index 69eac92..09ff1c8 100644
--- a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml
+++ b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml
@@ -8,7 +8,7 @@
         android:layout_gravity="center_vertical"
         android:layout_weight="1"
         android:orientation="vertical"
-        android:paddingLeft="16dp"
+        android:paddingStart="16dp"
         >
         <TextView android:id="@+id/title"
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
@@ -43,8 +43,8 @@
         android:layout_gravity="bottom"
         android:layout_marginBottom="13dip"
         android:scaleType="center"
-        android:layout_marginRight="4dip"
-        android:layout_marginLeft="16dip"
+        android:layout_marginEnd="4dip"
+        android:layout_marginStart="16dip"
         />
 </LinearLayout>
 
diff --git a/core/res/res/layout-w600dp/preference_list_content_single.xml b/core/res/res/layout-w600dp/preference_list_content_single.xml
index bbad296..d2fa5b9 100644
--- a/core/res/res/layout-w600dp/preference_list_content_single.xml
+++ b/core/res/res/layout-w600dp/preference_list_content_single.xml
@@ -34,8 +34,8 @@
             android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:paddingLeft="32dip"
-            android:paddingRight="32dip"
+            android:paddingStart="32dip"
+            android:paddingEnd="32dip"
             android:paddingTop="32dip"
             android:paddingBottom="32dip" >
 
@@ -67,14 +67,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml
index 5093a5e..edf6ee6 100644
--- a/core/res/res/layout-xlarge/activity_list.xml
+++ b/core/res/res/layout-xlarge/activity_list.xml
@@ -22,8 +22,8 @@
     android:orientation="vertical"
     android:paddingTop="9dip"
     android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip"
+    android:paddingStart="3dip"
+    android:paddingEnd="1dip"
     android:majorWeightMin="0.45"
     android:minorWeightMin="0.72"
     android:majorWeightMax="0.45"
@@ -37,14 +37,14 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:minHeight="60dip"
-            android:layout_marginLeft="32dip"
-            android:layout_marginRight="32dip">
+            android:layout_marginStart="32dip"
+            android:layout_marginEnd="32dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingRight="16dip"
+                android:paddingEnd="16dip"
                 android:src="@null"
                 android:visibility="gone" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
@@ -104,7 +104,7 @@
                 android:visibility="gone" />
             <Button android:id="@+id/button1"
                 android:layout_width="0dip"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 android:maxLines="2"
                 android:text="@string/cancel"
diff --git a/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml b/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
index 384c4fe..0fb3443 100644
--- a/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
+++ b/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
@@ -18,8 +18,8 @@
         android:orientation="vertical"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
-        android:layout_marginLeft="@dimen/preference_fragment_padding_side"
-        android:layout_marginRight="@dimen/preference_fragment_padding_side"
+        android:layout_marginStart="@dimen/preference_fragment_padding_side"
+        android:layout_marginEnd="@dimen/preference_fragment_padding_side"
     >
     <android.app.FragmentBreadCrumbs
             android:id="@android:id/title"
@@ -27,7 +27,7 @@
             android:layout_width="match_parent"
             android:paddingTop="16dip"
             android:paddingBottom="8dip"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
         />
 
     <ImageView
diff --git a/core/res/res/layout-xlarge/select_dialog_holo.xml b/core/res/res/layout-xlarge/select_dialog_holo.xml
index 7c95693..f931cf2 100644
--- a/core/res/res/layout-xlarge/select_dialog_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_holo.xml
@@ -28,8 +28,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_marginTop="5dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:cacheColorHint="@null"
     android:divider="?android:attr/listDividerAlertDialog"
     android:scrollbars="vertical"
diff --git a/core/res/res/layout-xlarge/select_dialog_item_holo.xml b/core/res/res/layout-xlarge/select_dialog_item_holo.xml
index 396092e..5f14e36 100644
--- a/core/res/res/layout-xlarge/select_dialog_item_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_item_holo.xml
@@ -30,7 +30,7 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml b/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml
index 8027035..63edc86 100644
--- a/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml b/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml
index cab519f..6a00d0d 100644
--- a/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index 96467d0..91af7e9 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -21,15 +21,15 @@
       android:background="?android:attr/actionBarItemBackground" >
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
-               android:layout_gravity="center_vertical|left"
+               android:layout_gravity="center_vertical|start"
                android:visibility="gone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
-               android:layout_marginRight="-8dip" />
+               android:layout_marginEnd="-8dip" />
     <ImageView android:id="@android:id/home"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
-               android:layout_marginRight="8dip"
+               android:layout_marginEnd="8dip"
                android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
                android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
                android:layout_gravity="center"
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index 2e21383..3ac0e21 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -18,20 +18,20 @@
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:orientation="horizontal"
-              android:paddingRight="8dip"
+              android:paddingEnd="8dip"
               android:background="?android:attr/actionBarItemBackground"
               android:enabled="false">
 
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
-               android:layout_gravity="center_vertical|left"
+               android:layout_gravity="center_vertical|start"
                android:visibility="gone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
 
     <LinearLayout android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:layout_gravity="center_vertical|left"
+                  android:layout_gravity="center_vertical|start"
                   android:orientation="vertical">
         <TextView android:id="@+id/action_bar_title"
                   android:layout_width="wrap_content"
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index ba7cf3b..04d1f7b 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -22,8 +22,8 @@
     android:focusable="true"
     android:paddingTop="4dip"
     android:paddingBottom="4dip"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip"
     android:textAppearance="?attr/actionMenuTextAppearance"
     android:textColor="?attr/actionMenuTextColor"
     style="?android:attr/actionButtonStyle" />
diff --git a/core/res/res/layout/action_mode_close_item.xml b/core/res/res/layout/action_mode_close_item.xml
index 8cd0cdd..3df83d0 100644
--- a/core/res/res/layout/action_mode_close_item.xml
+++ b/core/res/res/layout/action_mode_close_item.xml
@@ -18,12 +18,12 @@
         android:id="@+id/action_mode_close_button"
         android:focusable="true"
         android:clickable="true"
-        android:paddingLeft="8dip"
+        android:paddingStart="8dip"
         android:contentDescription="@string/action_mode_done"
         style="?android:attr/actionModeCloseButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_marginRight="16dip">
+        android:layout_marginEnd="16dip">
     <ImageView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml
index 4057441..bef17d0 100644
--- a/core/res/res/layout/activity_chooser_view.xml
+++ b/core/res/res/layout/activity_chooser_view.xml
@@ -38,8 +38,8 @@
             android:layout_gravity="center"
             android:layout_marginTop="2dip"
             android:layout_marginBottom="2dip"
-            android:layout_marginLeft="12dip"
-            android:layout_marginRight="12dip"
+            android:layout_marginStart="12dip"
+            android:layout_marginEnd="12dip"
             android:scaleType="fitCenter"
             android:adjustViewBounds="true" />
 
@@ -60,8 +60,8 @@
             android:layout_gravity="center"
             android:layout_marginTop="2dip"
             android:layout_marginBottom="2dip"
-            android:layout_marginLeft="12dip"
-            android:layout_marginRight="12dip"
+            android:layout_marginStart="12dip"
+            android:layout_marginEnd="12dip"
             android:scaleType="fitCenter"
             android:adjustViewBounds="true" />
 
diff --git a/core/res/res/layout/activity_chooser_view_list_item.xml b/core/res/res/layout/activity_chooser_view_list_item.xml
index 88498d9..af70234 100644
--- a/core/res/res/layout/activity_chooser_view_list_item.xml
+++ b/core/res/res/layout/activity_chooser_view_list_item.xml
@@ -18,8 +18,8 @@
     android:id="@+id/list_item"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/dropdownListPreferredItemHeight"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:minWidth="196dip"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:orientation="vertical" >
@@ -34,7 +34,7 @@
             android:layout_width="32dip"
             android:layout_height="32dip"
             android:layout_gravity="center_vertical"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:duplicateParentState="true" />
 
         <TextView
diff --git a/core/res/res/layout/activity_list_item.xml b/core/res/res/layout/activity_list_item.xml
index 572caf0..d639aa0 100644
--- a/core/res/res/layout/activity_list_item.xml
+++ b/core/res/res/layout/activity_list_item.xml
@@ -22,8 +22,8 @@
     android:layout_height="wrap_content"
     android:paddingTop="1dip"
     android:paddingBottom="1dip"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip">
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip">
 
     <ImageView android:id="@+id/icon"
         android:layout_width="24dip"
@@ -33,6 +33,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
-        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" />
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart" />
 </LinearLayout>
 
diff --git a/core/res/res/layout/activity_list_item_2.xml b/core/res/res/layout/activity_list_item_2.xml
index a58ebfc..a5a4cf9 100644
--- a/core/res/res/layout/activity_list_item_2.xml
+++ b/core/res/res/layout/activity_list_item_2.xml
@@ -21,5 +21,5 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:drawablePadding="14dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip" />
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip" />
diff --git a/core/res/res/layout/adaptive_notification_wrapper.xml b/core/res/res/layout/adaptive_notification_wrapper.xml
index df9d720..2583339 100644
--- a/core/res/res/layout/adaptive_notification_wrapper.xml
+++ b/core/res/res/layout/adaptive_notification_wrapper.xml
@@ -21,9 +21,9 @@
     android:id="@android:id/text1"
     android:textAppearance="?android:attr/dropDownHintAppearance"
     android:singleLine="true"
-    android:layout_marginLeft="3dip"
+    android:layout_marginStart="3dip"
     android:layout_marginTop="3dip"
-    android:layout_marginRight="3dip"
+    android:layout_marginEnd="3dip"
     android:layout_marginBottom="3dip"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />
diff --git a/core/res/res/layout/alert_dialog.xml b/core/res/res/layout/alert_dialog.xml
index 4477e07..35552d3 100644
--- a/core/res/res/layout/alert_dialog.xml
+++ b/core/res/res/layout/alert_dialog.xml
@@ -26,8 +26,8 @@
     android:orientation="vertical"
     android:paddingTop="9dip"
     android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip">
+    android:paddingStart="3dip"
+    android:paddingEnd="1dip">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
@@ -41,14 +41,14 @@
             android:gravity="center_vertical"
             android:layout_marginTop="6dip"
             android:layout_marginBottom="9dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip">
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="top"
                 android:paddingTop="6dip"
-                android:paddingRight="10dip"
+                android:paddingEnd="10dip"
                 android:src="@drawable/ic_dialog_info" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
                 style="?android:attr/textAppearanceLarge"
@@ -77,8 +77,8 @@
             android:layout_height="wrap_content"
             android:paddingTop="2dip"
             android:paddingBottom="12dip"
-            android:paddingLeft="14dip"
-            android:paddingRight="10dip"
+            android:paddingStart="14dip"
+            android:paddingEnd="10dip"
             android:overScrollMode="ifContentScrolls">
             <TextView android:id="@+id/message"
                 style="?android:attr/textAppearanceMedium"
@@ -110,8 +110,8 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:paddingTop="4dip"
-            android:paddingLeft="2dip"
-            android:paddingRight="2dip"
+            android:paddingStart="2dip"
+            android:paddingEnd="2dip"
             android:measureWithLargestChild="true">
             <LinearLayout android:id="@+id/leftSpacer"
                 android:layout_weight="0.25"
@@ -121,7 +121,7 @@
                 android:visibility="gone" />
             <Button android:id="@+id/button1"
                 android:layout_width="0dip"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 style="?android:attr/buttonBarButtonStyle"
                 android:maxLines="2"
@@ -135,7 +135,7 @@
                 android:layout_height="wrap_content" />
             <Button android:id="@+id/button2"
                 android:layout_width="0dip"
-                android:layout_gravity="right"
+                android:layout_gravity="end"
                 android:layout_weight="1"
                 style="?android:attr/buttonBarButtonStyle"
                 android:maxLines="2"
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 173efa7..7fc31d8 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -22,8 +22,8 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginLeft="8dip"
-    android:layout_marginRight="8dip"
+    android:layout_marginStart="8dip"
+    android:layout_marginEnd="8dip"
     android:orientation="vertical">
 
     <LinearLayout android:id="@+id/topPanel"
@@ -39,14 +39,14 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:minHeight="@dimen/alert_dialog_title_height"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip">
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingRight="8dip"
+                android:paddingEnd="8dip"
                 android:src="@null" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
                 style="?android:attr/windowTitleStyle"
@@ -76,8 +76,8 @@
                 style="?android:attr/textAppearanceMedium"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
                 android:paddingTop="8dip"
                 android:paddingBottom="8dip"/>
         </ScrollView>
@@ -109,7 +109,7 @@
             android:measureWithLargestChild="true">
             <Button android:id="@+id/button2"
                 android:layout_width="wrap_content"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 android:maxLines="2"
                 style="?android:attr/buttonBarButtonStyle"
@@ -127,7 +127,7 @@
                 android:layout_height="wrap_content" />
             <Button android:id="@+id/button1"
                 android:layout_width="wrap_content"
-                android:layout_gravity="right"
+                android:layout_gravity="end"
                 android:layout_weight="1"
                 android:maxLines="2"
                 android:minHeight="@dimen/alert_dialog_button_bar_height"
diff --git a/core/res/res/layout/alert_dialog_progress.xml b/core/res/res/layout/alert_dialog_progress.xml
index ac95cdb..fe06b65 100644
--- a/core/res/res/layout/alert_dialog_progress.xml
+++ b/core/res/res/layout/alert_dialog_progress.xml
@@ -22,17 +22,17 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="12dip"
             android:layout_marginBottom="1dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip"
             android:layout_centerHorizontal="true" />
         <TextView
             android:id="@+id/progress_percent"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="12dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip"
+            android:layout_alignParentStart="true"
             android:layout_below="@id/progress"
         />
         <TextView
@@ -40,9 +40,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="12dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"
-            android:layout_alignParentRight="true"
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip"
+            android:layout_alignParentEnd="true"
             android:layout_below="@id/progress"
         />
 </RelativeLayout>
diff --git a/core/res/res/layout/alert_dialog_progress_holo.xml b/core/res/res/layout/alert_dialog_progress_holo.xml
index 94dbb2b..41773d2 100644
--- a/core/res/res/layout/alert_dialog_progress_holo.xml
+++ b/core/res/res/layout/alert_dialog_progress_holo.xml
@@ -22,17 +22,17 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="1dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
             android:layout_centerHorizontal="true" />
         <TextView
             android:id="@+id/progress_percent"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="16dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
+            android:layout_alignParentStart="true"
             android:layout_below="@id/progress"
         />
         <TextView
@@ -40,9 +40,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="16dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:layout_alignParentRight="true"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
+            android:layout_alignParentEnd="true"
             android:layout_below="@id/progress"
         />
 </RelativeLayout>
diff --git a/core/res/res/layout/always_use_checkbox.xml b/core/res/res/layout/always_use_checkbox.xml
index a955352..16a1bb2d 100644
--- a/core/res/res/layout/always_use_checkbox.xml
+++ b/core/res/res/layout/always_use_checkbox.xml
@@ -20,8 +20,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingLeft="14dip"
-    android:paddingRight="15dip"
+    android:paddingStart="14dip"
+    android:paddingEnd="15dip"
     android:orientation="vertical">
     
     <CheckBox
@@ -36,7 +36,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:paddingLeft="36dip"
+        android:paddingStart="36dip"
         android:visibility="gone"
         android:text="@string/clearDefaultHintMsg" />
 </LinearLayout>
diff --git a/core/res/res/layout/am_compat_mode_dialog.xml b/core/res/res/layout/am_compat_mode_dialog.xml
index a8d39cf..8a0975d 100644
--- a/core/res/res/layout/am_compat_mode_dialog.xml
+++ b/core/res/res/layout/am_compat_mode_dialog.xml
@@ -17,7 +17,7 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent" android:layout_height="match_parent"
-        android:layout_marginLeft="40dp" android:layout_marginRight="40dp"
+        android:layout_marginStart="40dp" android:layout_marginEnd="40dp"
         android:layout_marginTop="15dp" android:layout_marginBottom="15dp"
         android:orientation="vertical">
     <LinearLayout
@@ -25,7 +25,7 @@
             android:layout_gravity="center_horizontal"
             android:orientation="horizontal" android:baselineAligned="true">
         <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
-                android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
+                android:layout_marginStart="10dp" android:layout_marginEnd="10dp"
                 android:textColor="?android:attr/textColorPrimary"
                 android:textSize="18sp"
                 android:text="@string/screen_compat_mode_scale"
@@ -35,7 +35,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
-                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
                 />
     </LinearLayout>
 
diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
index 1bd267f..ce0cd42 100644
--- a/core/res/res/layout/app_permission_item.xml
+++ b/core/res/res/layout/app_permission_item.xml
@@ -28,7 +28,7 @@
         android:id="@+id/perm_icon"
         android:layout_width="30dip"
         android:layout_height="30dip"
-        android:layout_alignParentLeft="true" 
+        android:layout_alignParentStart="true"
         android:scaleType="fitCenter" />
 
 
@@ -36,8 +36,8 @@
         android:id="@+id/permission_group"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/perm_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/perm_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -46,9 +46,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/permission_group"
-        android:layout_toRightOf="@id/perm_icon"
+        android:layout_toEndOf="@id/perm_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/app_permission_item_old.xml b/core/res/res/layout/app_permission_item_old.xml
index 1bd267f..ce0cd42 100644
--- a/core/res/res/layout/app_permission_item_old.xml
+++ b/core/res/res/layout/app_permission_item_old.xml
@@ -28,7 +28,7 @@
         android:id="@+id/perm_icon"
         android:layout_width="30dip"
         android:layout_height="30dip"
-        android:layout_alignParentLeft="true" 
+        android:layout_alignParentStart="true"
         android:scaleType="fitCenter" />
 
 
@@ -36,8 +36,8 @@
         android:id="@+id/permission_group"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/perm_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/perm_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -46,9 +46,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/permission_group"
-        android:layout_toRightOf="@id/perm_icon"
+        android:layout_toEndOf="@id/perm_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/app_perms_summary.xml b/core/res/res/layout/app_perms_summary.xml
index 3f99dde..829d15f 100755
--- a/core/res/res/layout/app_perms_summary.xml
+++ b/core/res/res/layout/app_perms_summary.xml
@@ -26,8 +26,8 @@
         android:id="@+id/no_permissions"
         android:text="@string/no_permissions"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="12dip"
         android:visibility="gone"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
@@ -37,8 +37,8 @@
         android:id="@+id/dangerous_perms_list"
         android:orientation="vertical"
         android:layout_width="match_parent"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="12dip"
         android:layout_height="wrap_content" />
 
     <!-- Clickable area letting user display additional permissions. -->
@@ -62,7 +62,7 @@
             android:layout_height="wrap_content"
             android:paddingTop="16dip"
             android:paddingBottom="12dip"
-            android:paddingLeft="16dip"
+            android:paddingStart="16dip"
             android:duplicateParentState="true"
             android:background="?android:attr/selectableItemBackground">
 
@@ -72,7 +72,7 @@
                 android:duplicateParentState="true"
                 android:layout_alignTop="@+id/show_more_icon"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="36dip"
+                android:paddingStart="36dip"
                 android:layout_weight="1"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content" />
@@ -81,7 +81,7 @@
                 android:id="@id/show_more_icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="12dip" />
+                android:layout_marginEnd="12dip" />
 
         </LinearLayout>
 
@@ -96,8 +96,8 @@
     <LinearLayout
         android:id="@+id/non_dangerous_perms_list"
         android:orientation="vertical"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="12dip"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/auto_complete_list.xml b/core/res/res/layout/auto_complete_list.xml
index 8ad5dbb..72beb2b 100644
--- a/core/res/res/layout/auto_complete_list.xml
+++ b/core/res/res/layout/auto_complete_list.xml
@@ -27,7 +27,7 @@
         android:orientation="vertical"
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"
-        android:paddingRight="0dip"
+        android:paddingEnd="0dip"
     />
 
     <AutoCompleteTextView android:id="@+id/edit"
diff --git a/core/res/res/layout/browser_link_context_header.xml b/core/res/res/layout/browser_link_context_header.xml
index b09ee1f..fef01b3 100644
--- a/core/res/res/layout/browser_link_context_header.xml
+++ b/core/res/res/layout/browser_link_context_header.xml
@@ -21,6 +21,6 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:maxLines="2"
-    android:paddingLeft="10dip"
-    android:paddingRight="10dip"
+    android:paddingStart="10dip"
+    android:paddingEnd="10dip"
     />
diff --git a/core/res/res/layout/calendar_view.xml b/core/res/res/layout/calendar_view.xml
index 176bb8b..bccb056 100644
--- a/core/res/res/layout/calendar_view.xml
+++ b/core/res/res/layout/calendar_view.xml
@@ -35,8 +35,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="6dip"
-        android:layout_marginRight="2dip"
-        android:layout_marginLeft="2dip"
+        android:layout_marginEnd="2dip"
+        android:layout_marginStart="2dip"
         android:gravity="center" >
 
         <TextView android:layout_width="0dip"
diff --git a/core/res/res/layout/character_picker.xml b/core/res/res/layout/character_picker.xml
index 2508f72e..3ddbbb2 100644
--- a/core/res/res/layout/character_picker.xml
+++ b/core/res/res/layout/character_picker.xml
@@ -28,7 +28,7 @@
         android:padding="4dp"
         android:verticalSpacing="8dp"
         android:horizontalSpacing="8dp"
-        android:gravity="left"
+        android:gravity="start"
         android:drawSelectorOnTop="false"
         android:numColumns="4"
         android:columnWidth="48dp"
@@ -41,8 +41,8 @@
         android:id="@+id/cancel"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="12dp"
-        android:layout_marginRight="12dp"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
         android:background="@drawable/btn_close"
         android:layout_gravity="center_vertical"
     />
diff --git a/core/res/res/layout/choose_account.xml b/core/res/res/layout/choose_account.xml
index c37a949..45a944e 100644
--- a/core/res/res/layout/choose_account.xml
+++ b/core/res/res/layout/choose_account.xml
@@ -21,8 +21,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip">
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip">
 
     <ListView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@android:id/list"
diff --git a/core/res/res/layout/choose_account_row.xml b/core/res/res/layout/choose_account_row.xml
index 33764a3..c4247b6 100644
--- a/core/res/res/layout/choose_account_row.xml
+++ b/core/res/res/layout/choose_account_row.xml
@@ -18,14 +18,14 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:orientation="horizontal" >
 
    <ImageView android:id="@+id/account_row_icon"
         android:layout_width="wrap_content"
         android:layout_height="fill_parent"
-        android:paddingRight="8dip" />
+        android:paddingEnd="8dip" />
 
     <TextView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/account_row_text"
diff --git a/core/res/res/layout/choose_account_type.xml b/core/res/res/layout/choose_account_type.xml
index db96dc1..769d80b 100644
--- a/core/res/res/layout/choose_account_type.xml
+++ b/core/res/res/layout/choose_account_type.xml
@@ -21,14 +21,14 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip">
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip">
 
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:layout_gravity="left"
+        android:layout_gravity="start"
         android:text="@string/add_account_label"
         android:paddingTop="16dip"
         android:paddingBottom="16dip"
diff --git a/core/res/res/layout/choose_type_and_account.xml b/core/res/res/layout/choose_type_and_account.xml
index 9d1d284..bf06054 100644
--- a/core/res/res/layout/choose_type_and_account.xml
+++ b/core/res/res/layout/choose_type_and_account.xml
@@ -27,11 +27,11 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:layout_gravity="left|center_vertical"
+        android:layout_gravity="start|center_vertical"
         android:paddingTop="16dip"
         android:paddingBottom="16dip"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
     />
 
     <!-- List of accounts, with "Add new account" as the last item -->
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 9c1def2..303ab30 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -41,8 +41,8 @@
             android:id="@+id/month"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="1dip"
-            android:layout_marginRight="1dip"
+            android:layout_marginStart="1dip"
+            android:layout_marginEnd="1dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -52,8 +52,8 @@
             android:id="@+id/day"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="1dip"
-            android:layout_marginRight="1dip"
+            android:layout_marginStart="1dip"
+            android:layout_marginEnd="1dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -63,8 +63,8 @@
             android:id="@+id/year"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="1dip"
-            android:layout_marginRight="1dip"
+            android:layout_marginStart="1dip"
+            android:layout_marginEnd="1dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -76,7 +76,7 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="44dip"
+        android:layout_marginStart="44dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index 8008682..b465d97 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -43,8 +43,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginStart="8dip"
+            android:layout_marginEnd="8dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -56,8 +56,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginStart="8dip"
+            android:layout_marginEnd="8dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -69,8 +69,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="8dip"
+            android:layout_marginEnd="16dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -82,8 +82,8 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/dialog_custom_title.xml b/core/res/res/layout/dialog_custom_title.xml
index 3784c59..2dda5e5 100644
--- a/core/res/res/layout/dialog_custom_title.xml
+++ b/core/res/res/layout/dialog_custom_title.xml
@@ -37,8 +37,8 @@
             android:layout_height="match_parent"
             android:paddingTop="6dip"
             android:paddingBottom="10dip"
-            android:paddingLeft="10dip"
-            android:paddingRight="10dip" />
+            android:paddingStart="10dip"
+            android:paddingEnd="10dip" />
     </FrameLayout>
 </LinearLayout>
 
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index cf71197..f8a2bf7 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -25,7 +25,7 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/alert_dialog_title_height"
         android:layout_weight="0"
-        android:gravity="center_vertical|left"
+        android:gravity="center_vertical|start"
         style="?android:attr/windowTitleBackgroundStyle">
     </FrameLayout>
     <View android:id="@+id/titleDivider"
diff --git a/core/res/res/layout/dialog_title.xml b/core/res/res/layout/dialog_title.xml
index 949f86e..40eb385 100644
--- a/core/res/res/layout/dialog_title.xml
+++ b/core/res/res/layout/dialog_title.xml
@@ -30,8 +30,8 @@
         android:minHeight="53dip"
         android:paddingTop="9dip"
         android:paddingBottom="9dip"
-        android:paddingLeft="10dip"
-        android:paddingRight="10dip" />
+        android:paddingStart="10dip"
+        android:paddingEnd="10dip" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
index 50bb0ba..0a692ee 100644
--- a/core/res/res/layout/dialog_title_holo.xml
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -27,9 +27,9 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:minHeight="@android:dimen/alert_dialog_title_height"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
-        android:gravity="center_vertical|left" />
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
+        android:gravity="center_vertical|start" />
     <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
             android:layout_height="2dip"
diff --git a/core/res/res/layout/dialog_title_icons.xml b/core/res/res/layout/dialog_title_icons.xml
index 0ca6706..a86a76c 100644
--- a/core/res/res/layout/dialog_title_icons.xml
+++ b/core/res/res/layout/dialog_title_icons.xml
@@ -31,8 +31,8 @@
         android:minHeight="53dip"
         android:paddingTop="6dip"
         android:paddingBottom="9dip"
-        android:paddingLeft="10dip"
-        android:paddingRight="10dip">
+        android:paddingStart="10dip"
+        android:paddingEnd="10dip">
         <ImageView android:id="@+id/left_icon"
             android:layout_width="32dip"
             android:layout_height="32dip"
@@ -46,8 +46,8 @@
             android:layout_weight="0"
             android:paddingTop="2dip"
             android:paddingBottom="1dip"
-            android:paddingLeft="14dip"
-            android:paddingRight="14dip" />
+            android:paddingStart="14dip"
+            android:paddingEnd="14dip" />
         <ImageView android:id="@+id/right_icon"
             android:layout_width="32dip"
             android:layout_height="32dip"
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
index 7d7959f..e3d771c 100644
--- a/core/res/res/layout/dialog_title_icons_holo.xml
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -29,13 +29,13 @@
         android:orientation="horizontal"
         android:gravity="center_vertical"
         android:minHeight="@android:dimen/alert_dialog_title_height"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip">
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip">
         <ImageView android:id="@+id/left_icon"
             android:layout_width="32dip"
             android:layout_height="32dip"
             android:scaleType="fitCenter"
-            android:layout_marginRight="8dip" />
+            android:layout_marginEnd="8dip" />
         <TextView android:id="@android:id/title"
             style="?android:attr/windowTitleStyle"
             android:layout_width="wrap_content"
@@ -45,7 +45,7 @@
             android:layout_width="32dip"
             android:layout_height="32dip"
             android:scaleType="fitCenter"
-            android:layout_marginLeft="8dip" />
+            android:layout_marginStart="8dip" />
     </LinearLayout>
 
     <View android:id="@+id/titleDivider"
diff --git a/core/res/res/layout/fragment_bread_crumb_item.xml b/core/res/res/layout/fragment_bread_crumb_item.xml
index dbbb9a5..ee4344f 100644
--- a/core/res/res/layout/fragment_bread_crumb_item.xml
+++ b/core/res/res/layout/fragment_bread_crumb_item.xml
@@ -32,8 +32,8 @@
             android:id="@+id/title"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
+            android:paddingStart="8dip"
+            android:paddingEnd="8dip"
             android:gravity="center_vertical"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:background="?android:attr/selectableItemBackground"
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index 694301e..bf9c638 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -22,16 +22,16 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:orientation="horizontal"
 
-    android:paddingLeft="16dip"
+    android:paddingStart="16dip"
     android:paddingTop="6dip"
     android:paddingBottom="6dip"
     >
     <ImageView android:id="@+id/icon"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_width="56dp"
+        android:layout_height="56dp"
         android:layout_gravity="center"
-        android:layout_marginRight="16dip"
-        />
+        android:layout_marginEnd="16dip"
+        android:scaleType="center"/>
 
     <LinearLayout
         android:orientation="vertical"
diff --git a/core/res/res/layout/global_actions_silent_mode.xml b/core/res/res/layout/global_actions_silent_mode.xml
index 18b4715..79401af 100644
--- a/core/res/res/layout/global_actions_silent_mode.xml
+++ b/core/res/res/layout/global_actions_silent_mode.xml
@@ -33,8 +33,8 @@
             android:layout_width="48dp"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:src="@drawable/ic_audio_vol_mute"
@@ -61,8 +61,8 @@
             android:layout_width="48dp"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:src="@drawable/ic_audio_ring_notif_vibrate"
@@ -90,8 +90,8 @@
             android:layout_width="48dp"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:src="@drawable/ic_audio_vol"
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index dd85b33..e7ec539 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -47,20 +47,20 @@
                 android:layout_height="wrap_content"
                 android:text="@string/grant_credentials_permission_message_header"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:paddingLeft="19dip"
+                android:paddingStart="19dip"
                 android:paddingBottom="12dip" />
 
             <LinearLayout
                 android:id="@+id/packages_list"
                 android:orientation="vertical"
-                android:paddingLeft="16dip"
-                android:paddingRight="12dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="12dip"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
 
             <RelativeLayout
-                android:paddingLeft="16dip"
-                android:paddingRight="12dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="12dip"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content">
 
@@ -69,7 +69,7 @@
                     android:layout_width="30dip"
                     android:layout_height="30dip"
                     android:src="@drawable/ic_bullet_key_permission"
-                    android:layout_alignParentLeft="true"
+                    android:layout_alignParentStart="true"
                     android:scaleType="fitCenter" />
 
                 <TextView
@@ -77,8 +77,8 @@
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:textColor="@color/perms_dangerous_perm_color"
                     android:textStyle="bold"
-                    android:paddingLeft="16dip"
-                    android:layout_toRightOf="@id/permission_icon"
+                    android:paddingStart="16dip"
+                    android:layout_toEndOf="@id/permission_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content" />
 
@@ -88,9 +88,9 @@
                     android:textColor="@color/perms_dangerous_perm_color"
                     android:layout_marginTop="-4dip"
                     android:paddingBottom="8dip"
-                    android:paddingLeft="16dip"
+                    android:paddingStart="16dip"
                     android:layout_below="@id/account_type"
-                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_toEndOf="@id/permission_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content" />
 
@@ -101,9 +101,9 @@
                     android:textStyle="bold"
                     android:layout_marginTop="-4dip"
                     android:paddingBottom="8dip"
-                    android:paddingLeft="16dip"
+                    android:paddingStart="16dip"
                     android:layout_below="@id/account_name"
-                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_toEndOf="@id/permission_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content" />
             </RelativeLayout>
@@ -114,7 +114,7 @@
                 android:layout_height="wrap_content"
                 android:text="@string/grant_credentials_permission_message_footer"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:paddingLeft="19dip"
+                android:paddingStart="19dip"
                 android:paddingBottom="12dip" />
         </LinearLayout>
     </ScrollView>
diff --git a/core/res/res/layout/heavy_weight_switcher.xml b/core/res/res/layout/heavy_weight_switcher.xml
index 9acf009..c17e555 100644
--- a/core/res/res/layout/heavy_weight_switcher.xml
+++ b/core/res/res/layout/heavy_weight_switcher.xml
@@ -36,8 +36,8 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:orientation="horizontal"
         android:background="@android:drawable/list_selector_background"
-        android:paddingRight="3dip"
-        android:paddingLeft="3dip"
+        android:paddingEnd="3dip"
+        android:paddingStart="3dip"
         android:paddingTop="5dip"
         android:paddingBottom="14dip"
         android:gravity="center_vertical"
@@ -46,7 +46,7 @@
         <ImageView android:id="@+id/old_app_icon"
             android:layout_width="@android:dimen/app_icon_size"
             android:layout_height="@android:dimen/app_icon_size"
-            android:layout_marginRight="11dip"
+            android:layout_marginEnd="11dip"
             android:layout_gravity="center_vertical"
             android:scaleType="fitCenter"/>
     
@@ -84,8 +84,8 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:orientation="horizontal"
         android:background="@android:drawable/list_selector_background"
-        android:paddingRight="3dip"
-        android:paddingLeft="3dip"
+        android:paddingEnd="3dip"
+        android:paddingStart="3dip"
         android:paddingTop="5dip"
         android:paddingBottom="8dip"
         android:gravity="center_vertical"
@@ -94,7 +94,7 @@
         <ImageView android:id="@+id/new_app_icon"
             android:layout_width="@android:dimen/app_icon_size"
             android:layout_height="@android:dimen/app_icon_size"
-            android:layout_marginRight="11dip"
+            android:layout_marginEnd="11dip"
             android:layout_gravity="center_vertical"
             android:scaleType="fitCenter"/>
     
@@ -132,8 +132,8 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:background="@android:drawable/list_selector_background"
-        android:paddingRight="6dip"
-        android:paddingLeft="6dip"
+        android:paddingEnd="6dip"
+        android:paddingStart="6dip"
         android:paddingTop="5dip"
         android:paddingBottom="8dip"
         android:textStyle="bold"
diff --git a/core/res/res/layout/icon_menu_item_layout.xml b/core/res/res/layout/icon_menu_item_layout.xml
index a73dccc..cdb5bfa 100644
--- a/core/res/res/layout/icon_menu_item_layout.xml
+++ b/core/res/res/layout/icon_menu_item_layout.xml
@@ -19,8 +19,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingBottom="1dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="3dip"
+    android:paddingStart="3dip"
+    android:paddingEnd="3dip"
     android:singleLine="true"
     android:ellipsize="marquee"
     android:fadingEdge="horizontal" />
diff --git a/core/res/res/layout/input_method_extract_view.xml b/core/res/res/layout/input_method_extract_view.xml
index a3e4961..269ff85 100644
--- a/core/res/res/layout/input_method_extract_view.xml
+++ b/core/res/res/layout/input_method_extract_view.xml
@@ -38,8 +38,8 @@
             android:id="@+id/inputExtractAccessories"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
+            android:paddingStart="8dip"
+            android:paddingEnd="8dip"
         >
         
         <android.inputmethodservice.ExtractButton android:id="@+id/inputExtractAction"
diff --git a/core/res/res/layout/input_method_switch_dialog_title.xml b/core/res/res/layout/input_method_switch_dialog_title.xml
index 7032bd3..e11a523 100644
--- a/core/res/res/layout/input_method_switch_dialog_title.xml
+++ b/core/res/res/layout/input_method_switch_dialog_title.xml
@@ -25,8 +25,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="9dip"
-        android:layout_marginLeft="20dip"
-        android:layout_marginRight="10dip"
+        android:layout_marginStart="20dip"
+        android:layout_marginEnd="10dip"
         android:layout_marginTop="6dip"
         android:gravity="center_vertical"
         android:orientation="vertical" >
@@ -69,8 +69,8 @@
                 android:minHeight="?android:attr/listPreferredItemHeightSmall"
                 android:orientation="vertical"
                 android:paddingBottom="5dip"
-                android:paddingLeft="16dip"
-                android:paddingRight="0dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="0dip"
                 android:paddingTop="5dip" >
 
                 <TextView
@@ -95,7 +95,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
-                android:layout_marginRight="12dip" />
+                android:layout_marginEnd="12dip" />
         </LinearLayout>
     </LinearLayout>
 
diff --git a/core/res/res/layout/keyboard_popup_keyboard.xml b/core/res/res/layout/keyboard_popup_keyboard.xml
index 5eb2732..6f222bf 100644
--- a/core/res/res/layout/keyboard_popup_keyboard.xml
+++ b/core/res/res/layout/keyboard_popup_keyboard.xml
@@ -41,7 +41,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:layout_marginLeft="8dp"
+        android:layout_marginStart="8dp"
         android:clickable="true"
         />
 </LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard.xml b/core/res/res/layout/keyguard.xml
index ca629f8..f8f482d 100644
--- a/core/res/res/layout/keyguard.xml
+++ b/core/res/res/layout/keyguard.xml
@@ -19,9 +19,9 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:paddingLeft="20dip"
+    android:paddingStart="20dip"
     android:paddingTop="20dip"
-    android:paddingRight="20dip"
+    android:paddingEnd="20dip"
     android:paddingBottom="20dip"
     android:orientation="vertical" 
     android:layout_width="wrap_content"
diff --git a/core/res/res/layout/keyguard_screen_glogin_unlock.xml b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
index 35d113c..db920b4 100644
--- a/core/res/res/layout/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
@@ -37,7 +37,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_marginLeft="4dip"
+                android:layout_marginStart="4dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:gravity="center_vertical"
                 android:drawableLeft="@drawable/ic_lock_idle_lock"
@@ -58,7 +58,7 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@+id/spacerTop"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="9dip"
+                android:layout_marginStart="9dip"
                 android:textAppearance="?android:attr/textAppearanceSmall"
                 android:text="@android:string/lockscreen_glogin_instructions"
                 />
@@ -69,8 +69,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/instructions"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:hint="@android:string/lockscreen_glogin_username_hint"
                 android:inputType="textEmailAddress"
                 />
@@ -81,8 +81,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/login"
                 android:layout_marginTop="15dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:inputType="textPassword"
                 android:hint="@android:string/lockscreen_glogin_password_hint"
                 android:nextFocusRight="@+id/ok"
@@ -96,8 +96,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/password"
                 android:layout_marginTop="7dip"
-                android:layout_marginRight="7dip"
-                android:layout_alignParentRight="true"
+                android:layout_marginEnd="7dip"
+                android:layout_alignParentEnd="true"
                 android:text="@android:string/lockscreen_glogin_submit_button"
                 />
         
diff --git a/core/res/res/layout/keyguard_screen_lock.xml b/core/res/res/layout/keyguard_screen_lock.xml
index 43867f4..8c178b1 100644
--- a/core/res/res/layout/keyguard_screen_lock.xml
+++ b/core/res/res/layout/keyguard_screen_lock.xml
@@ -34,8 +34,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginBottom="15dip"
-        android:layout_marginLeft="15dip"
-        android:layout_marginRight="15dip"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="15dip"
         android:paddingTop="20dip"
         android:paddingBottom="20dip"
         android:background="@android:drawable/popup_full_dark"
@@ -108,7 +108,7 @@
             <ImageView android:id="@+id/batteryInfoIcon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:gravity="center"
             />
@@ -143,7 +143,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_alarm"
                 android:gravity="center"
@@ -177,7 +177,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_lock"
                 android:gravity="center"
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 3bea16c..71fb363 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -33,7 +33,7 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="8dip"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:layout_rowSpan="2">
 
        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
@@ -58,7 +58,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -68,7 +68,7 @@
         android:id="@+id/date"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_below="@id/time"
         android:layout_marginTop="6dip"
         android:singleLine="true"
@@ -85,14 +85,14 @@
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         android:layout_marginTop="4dip"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         />
 
     <TextView
         android:id="@+id/status1"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_marginTop="4dip"
         android:singleLine="true"
         android:ellipsize="marquee"
@@ -107,7 +107,7 @@
         android:id="@+id/carrier"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -117,7 +117,7 @@
 
     <Button
         android:id="@+id/emergencyCallButton"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:drawableLeft="@drawable/lockscreen_emergency_button"
         android:text="@string/lockscreen_emergency_call"
         style="?android:attr/buttonBarButtonStyle"
@@ -143,7 +143,7 @@
             android:layout_width="0dip"
             android:layout_weight="1"
             android:gravity="center"
-            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+            android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
             android:layout_gravity="center_vertical"
             android:singleLine="true"
             android:textStyle="normal"
@@ -185,8 +185,8 @@
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="270dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="4dip"
-        android:layout_marginRight="4dip"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
         android:background="#40000000"
         android:layout_marginTop="5dip"
         android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
@@ -233,7 +233,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 6b409aa..486c7fe 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -25,8 +25,8 @@
 
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginBottom="18dip"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
-        android:layout_gravity="right">
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -56,8 +56,8 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
@@ -73,7 +73,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -85,8 +85,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -102,8 +102,8 @@
         android:layout_gravity="center_vertical|fill_horizontal"
         android:orientation="horizontal"
         android:background="@drawable/lockscreen_password_field_dark"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip">
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip">
 
         <EditText android:id="@+id/passwordEntry"
             android:layout_width="0dip"
@@ -111,7 +111,7 @@
             android:layout_weight="1"
             android:gravity="center_horizontal"
             android:layout_gravity="center_vertical"
-            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+            android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
             android:singleLine="true"
             android:textStyle="normal"
             android:inputType="textPassword"
@@ -150,8 +150,8 @@
     <!-- Numeric keyboard -->
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="match_parent"
-        android:layout_marginLeft="4dip"
-        android:layout_marginRight="4dip"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
         android:paddingTop="4dip"
         android:paddingBottom="4dip"
         android:background="#40000000"
@@ -224,7 +224,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 3cb19c3..3738766 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -39,7 +39,7 @@
         android:layout_height="wrap_content"
         android:layout_above="@+id/pinDisplayGroup"
         android:layout_marginTop="9dip"
-        android:gravity="left|bottom"
+        android:gravity="start|bottom"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -54,9 +54,9 @@
         android:addStatesFromChildren="true"
         android:gravity="center_vertical"
         android:baselineAligned="false"
-        android:paddingRight="0dip"
-        android:layout_marginRight="30dip"
-        android:layout_marginLeft="30dip"
+        android:paddingEnd="0dip"
+        android:layout_marginEnd="30dip"
+        android:layout_marginStart="30dip"
         android:background="@android:drawable/edit_text"
     >
 
@@ -75,7 +75,7 @@
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_marginTop="2dip"
-             android:layout_marginRight="2dip"
+             android:layout_marginEnd="2dip"
              android:layout_marginBottom="2dip"
              android:gravity="center"
             />
@@ -88,8 +88,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip">
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip">
 
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
@@ -99,7 +99,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="4dip"
@@ -112,7 +112,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginStart="8dip"
             android:textSize="18sp"
         />
     </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
index 9ca351c..20c2142 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
@@ -51,8 +51,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:gravity="center_vertical"
             android:background="@android:drawable/edit_text">
 
@@ -72,7 +72,7 @@
                 android:src="@android:drawable/ic_input_delete"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="-3dip"
+                android:layout_marginEnd="-3dip"
                 android:layout_marginBottom="-3dip"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
index 56e6426..fd6dc26 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -55,8 +55,8 @@
                 android:orientation="vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginRight="10dip"
-                android:layout_marginLeft="10dip">
+                android:layout_marginEnd="10dip"
+                android:layout_marginStart="10dip">
                 <TextView android:id="@+id/enter_puk"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -78,16 +78,16 @@
                   android:layout_width="wrap_content"
                   android:layout_weight="1"
                   android:layout_height="match_parent"
-                  android:paddingRight="0dip"
-                  android:layout_marginRight="10dip"
-                  android:layout_marginLeft="10dip">
+                  android:paddingEnd="0dip"
+                  android:layout_marginEnd="10dip"
+                  android:layout_marginStart="10dip">
 
                   <LinearLayout
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -106,7 +106,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
@@ -116,8 +116,8 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -138,7 +138,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
@@ -152,8 +152,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip">
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip">
 
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
@@ -163,7 +163,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="4dip"
@@ -176,7 +176,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginStart="8dip"
             android:textSize="18sp"
         />
     </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
index 8b039f7..5397e62 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
@@ -35,8 +35,8 @@
             android:gravity="center"
             android:singleLine="true"
             android:ellipsize="marquee"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:textAppearance="?android:attr/textAppearanceLarge"/>
 
         <!-- Carrier info -->
@@ -47,8 +47,8 @@
             android:gravity="center"
             android:singleLine="true"
             android:ellipsize="marquee"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:textAppearance="?android:attr/textAppearanceMedium"/>
 
         <LinearLayout
@@ -61,16 +61,16 @@
                   android:layout_width="wrap_content"
                   android:layout_weight="1"
                   android:layout_height="match_parent"
-                  android:paddingRight="0dip"
-                  android:layout_marginRight="10dip"
-                  android:layout_marginLeft="10dip">
+                  android:paddingEnd="0dip"
+                  android:layout_marginEnd="10dip"
+                  android:layout_marginStart="10dip">
 
                   <LinearLayout
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -90,7 +90,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
@@ -100,8 +100,8 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -121,7 +121,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 81166222..54381ee 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -31,8 +31,8 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="@dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
         android:layout_marginBottom="12dip"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
-        android:layout_gravity="right">
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -56,7 +56,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -64,8 +64,8 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
@@ -81,7 +81,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -93,8 +93,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -110,8 +110,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="4dip"
-        android:layout_marginRight="16dip"
-        android:layout_gravity="right"
+        android:layout_marginEnd="16dip"
+        android:layout_gravity="end"
         android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
         style="?android:attr/buttonBarButtonStyle"
         android:drawablePadding="4dip"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 35e4d11..7ef9d8b 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -32,7 +32,7 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="80dip"
         android:layout_marginBottom="8dip"
-        android:layout_gravity="right">
+        android:layout_gravity="end">
 
        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -56,7 +56,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -66,7 +66,7 @@
         android:id="@+id/date"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_marginTop="6dip"
         android:singleLine="true"
         android:ellipsize="marquee"
@@ -82,14 +82,14 @@
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         android:layout_marginTop="4dip"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         />
 
     <TextView
         android:id="@+id/status1"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_marginTop="4dip"
         android:singleLine="true"
         android:ellipsize="marquee"
@@ -105,7 +105,7 @@
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
         android:layout_marginBottom="12dip"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -117,7 +117,7 @@
         android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
         android:text="@*android:string/lockscreen_emergency_call"
         style="?android:attr/buttonBarButtonStyle"
@@ -134,7 +134,7 @@
         android:layout_width="302dip"
         android:layout_height="match_parent"
         android:layout_rowSpan="7"
-        android:gravity="left|center_vertical"
+        android:gravity="start|center_vertical"
         android:focusable="true"
 
         android:targetDrawables="@array/lockscreen_targets_with_camera"
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 7f9aaa0..edd74e2 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -32,7 +32,7 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="12dip"
-        android:layout_gravity="right">
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -55,7 +55,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:layout_marginBottom="6dip"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             android:textColor="@color/lockscreen_clock_foreground"
             />
@@ -66,7 +66,7 @@
         android:id="@+id/date"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -79,7 +79,7 @@
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:drawablePadding="4dip"
         />
 
@@ -87,7 +87,7 @@
         android:id="@+id/status1"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -99,7 +99,7 @@
     <TextView android:id="@+id/carrier"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -109,11 +109,11 @@
     <LinearLayout
         style="?android:attr/buttonBarStyle"
         android:orientation="vertical"
-        android:layout_gravity="right">
+        android:layout_gravity="end">
 
         <Button android:id="@+id/emergencyCallButton"
             style="?android:attr/buttonBarButtonStyle"
-            android:layout_gravity="right"
+            android:layout_gravity="end"
             android:layout_width="wrap_content"
             android:layout_height="0dip"
             android:layout_weight="1"
@@ -125,7 +125,7 @@
 
         <Button android:id="@+id/forgotPatternButton"
             style="?android:attr/buttonBarButtonStyle"
-            android:layout_gravity="right"
+            android:layout_gravity="end"
             android:layout_width="wrap_content"
             android:layout_height="0dip"
             android:layout_weight="1"
@@ -142,9 +142,9 @@
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_marginTop="8dip"
-         android:layout_marginRight="8dip"
+         android:layout_marginEnd="8dip"
          android:layout_marginBottom="8dip"
-         android:layout_marginLeft="8dip"
+         android:layout_marginStart="8dip"
          android:layout_rowSpan="7"/>
 
 
@@ -169,7 +169,7 @@
         android:layout_rowSpan="7"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
-        android:layout_marginLeft="8dip"
+        android:layout_marginStart="8dip"
         android:layout_width="0dip"
         android:layout_height="0dip"
         android:background="@drawable/intro_bg">
@@ -187,7 +187,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index c235289..f20cbcd 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -30,8 +30,8 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="@dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
         android:layout_marginBottom="@dimen/keyguard_lockscreen_status_line_clockfont_bottom_margin"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
-        android:layout_gravity="right">
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -59,8 +59,8 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
@@ -76,7 +76,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -89,8 +89,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -108,9 +108,9 @@
         android:id="@+id/lockPattern"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginRight="8dip"
+        android:layout_marginEnd="8dip"
         android:layout_marginBottom="4dip"
-        android:layout_marginLeft="8dip"
+        android:layout_marginStart="8dip"
         android:layout_gravity="center_horizontal"
      />
 
@@ -196,7 +196,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_transport_control.xml b/core/res/res/layout/keyguard_transport_control.xml
index 7e2a31c..3e702df 100644
--- a/core/res/res/layout/keyguard_transport_control.xml
+++ b/core/res/res/layout/keyguard_transport_control.xml
@@ -47,8 +47,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
             android:gravity="center_horizontal"
             android:singleLine="true"
             android:ellipsize="end"
diff --git a/core/res/res/layout/list_menu_item_icon.xml b/core/res/res/layout/list_menu_item_icon.xml
index 27dd9b8..a30be6a 100644
--- a/core/res/res/layout/list_menu_item_icon.xml
+++ b/core/res/res/layout/list_menu_item_icon.xml
@@ -19,8 +19,8 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_vertical"
-    android:layout_marginLeft="8dip"
-    android:layout_marginRight="-8dip"
+    android:layout_marginStart="8dip"
+    android:layout_marginEnd="-8dip"
     android:layout_marginTop="8dip"
     android:layout_marginBottom="8dip"
     android:scaleType="centerInside"
diff --git a/core/res/res/layout/list_menu_item_layout.xml b/core/res/res/layout/list_menu_item_layout.xml
index 680eca7..0f37c71 100644
--- a/core/res/res/layout/list_menu_item_layout.xml
+++ b/core/res/res/layout/list_menu_item_layout.xml
@@ -26,8 +26,8 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
-        android:layout_marginRight="?android:attr/listPreferredItemPaddingRight"
+        android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
+        android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
         android:duplicateParentState="true">
         
         <TextView 
@@ -35,7 +35,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceListItemSmall"
             android:singleLine="true"
             android:duplicateParentState="true"
@@ -47,7 +47,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/title"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:singleLine="true"
             android:duplicateParentState="true" />
diff --git a/core/res/res/layout/locale_picker_item.xml b/core/res/res/layout/locale_picker_item.xml
index 19c0dee..94c9baf 100644
--- a/core/res/res/layout/locale_picker_item.xml
+++ b/core/res/res/layout/locale_picker_item.xml
@@ -20,10 +20,10 @@
     android:layout_width="match_parent"
     android:gravity="center_vertical"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:paddingLeft="16dp"
+    android:paddingStart="16dp"
     android:paddingTop="8dp"
     android:paddingBottom="8dp"
-    android:paddingRight="16dp">
+    android:paddingEnd="16dp">
 
     <TextView android:id="@+id/locale"
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml
index 313806cd..ad74a3a 100644
--- a/core/res/res/layout/media_controller.xml
+++ b/core/res/res/layout/media_controller.xml
@@ -44,11 +44,11 @@
             android:textSize="14sp"
             android:textStyle="bold"
             android:paddingTop="4dip"
-            android:paddingLeft="4dip"
+            android:paddingStart="4dip"
             android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingRight="4dip" />
+            android:paddingEnd="4dip" />
 
         <SeekBar
             android:id="@+id/mediacontroller_progress"
@@ -56,18 +56,18 @@
             android:layout_width="0dip"
             android:layout_weight="1"
             android:layout_height="32dip"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true" />
+            android:layout_alignParentStart="true"
+            android:layout_alignParentEnd="true" />
 
         <TextView android:id="@+id/time"
             android:textSize="14sp"
             android:textStyle="bold"
             android:paddingTop="4dip"
-            android:paddingRight="4dip"
+            android:paddingEnd="4dip"
             android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="4dip" />
+            android:paddingStart="4dip" />
     </LinearLayout>
 
 </LinearLayout>
diff --git a/core/res/res/layout/media_route_chooser_layout.xml b/core/res/res/layout/media_route_chooser_layout.xml
index 731c0d0..5fcb8c8 100644
--- a/core/res/res/layout/media_route_chooser_layout.xml
+++ b/core/res/res/layout/media_route_chooser_layout.xml
@@ -33,8 +33,8 @@
                  android:layout_width="0dp"
                  android:layout_height="wrap_content"
                  android:layout_weight="1"
-                 android:layout_marginLeft="8dp"
-                 android:layout_marginRight="8dp" />
+                 android:layout_marginStart="8dp"
+                 android:layout_marginEnd="8dp" />
         <ImageButton android:id="@+id/extended_settings"
                      android:layout_width="48dp"
                      android:layout_height="48dp"
diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml
index 8ce6327..53d813e 100644
--- a/core/res/res/layout/media_route_list_item.xml
+++ b/core/res/res/layout/media_route_list_item.xml
@@ -30,9 +30,9 @@
                   android:layout_height="match_parent"
                   android:layout_weight="1"
                   android:orientation="vertical"
-                  android:gravity="left|center_vertical"
-                  android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-                  android:paddingRight="?android:attr/listPreferredItemPaddingRight">
+                  android:gravity="start|center_vertical"
+                  android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+                  android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
 
         <TextView android:id="@android:id/text1"
                   android:layout_width="match_parent"
diff --git a/core/res/res/layout/media_route_list_item_checkable.xml b/core/res/res/layout/media_route_list_item_checkable.xml
index d0bffb6..5fb82f7 100644
--- a/core/res/res/layout/media_route_list_item_checkable.xml
+++ b/core/res/res/layout/media_route_list_item_checkable.xml
@@ -30,9 +30,9 @@
                   android:layout_height="match_parent"
                   android:layout_weight="1"
                   android:orientation="vertical"
-                  android:gravity="left|center_vertical"
-                  android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-                  android:paddingRight="?android:attr/listPreferredItemPaddingRight">
+                  android:gravity="start|center_vertical"
+                  android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+                  android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
 
         <TextView android:id="@android:id/text1"
                   android:layout_width="match_parent"
@@ -52,7 +52,7 @@
     <CheckBox
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginRight="16dp"
+        android:layout_marginEnd="16dp"
         android:id="@+id/check"
         android:focusable="false"
         android:clickable="false" />
diff --git a/core/res/res/layout/media_route_list_item_collapse_group.xml b/core/res/res/layout/media_route_list_item_collapse_group.xml
index d605c18..323e24d 100644
--- a/core/res/res/layout/media_route_list_item_collapse_group.xml
+++ b/core/res/res/layout/media_route_list_item_collapse_group.xml
@@ -22,8 +22,8 @@
         android:layout_width="match_parent"
         android:layout_height="?android:attr/listPreferredItemHeightSmall"
         android:background="#19ffffff"
-        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
         android:gravity="center_vertical">
 
         <TextView android:layout_width="0dp"
diff --git a/core/res/res/layout/media_route_list_item_section_header.xml b/core/res/res/layout/media_route_list_item_section_header.xml
index 04bd0ea..949635f 100644
--- a/core/res/res/layout/media_route_list_item_section_header.xml
+++ b/core/res/res/layout/media_route_list_item_section_header.xml
@@ -27,8 +27,8 @@
         android:textStyle="bold"
         android:textAllCaps="true"
         android:gravity="center_vertical"
-        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
         android:minHeight="24dp"
         />
 </FrameLayout>
diff --git a/core/res/res/layout/media_route_list_item_top_header.xml b/core/res/res/layout/media_route_list_item_top_header.xml
index 75decd3..0c49b24 100644
--- a/core/res/res/layout/media_route_list_item_top_header.xml
+++ b/core/res/res/layout/media_route_list_item_top_header.xml
@@ -23,7 +23,7 @@
     android:textStyle="bold"
     android:textAllCaps="true"
     android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:minHeight="24dp"
 />
diff --git a/core/res/res/layout/menu_item.xml b/core/res/res/layout/menu_item.xml
index 7e9859f..df6462e 100644
--- a/core/res/res/layout/menu_item.xml
+++ b/core/res/res/layout/menu_item.xml
@@ -20,26 +20,26 @@
 <MenuItemView xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:focusable="true" >
 
     <TextView android:id="@+id/index"
-        android:paddingLeft="0dip" android:paddingTop="1dip"
-        android:paddingRight="8dip" android:paddingBottom="0dip"
+        android:paddingStart="0dip" android:paddingTop="1dip"
+        android:paddingEnd="8dip" android:paddingBottom="0dip"
         android:layout_width="17dip" android:layout_height="wrap_content"
         android:includeFontPadding="false" />
 
     <ImageView android:id="@+id/check"
-        android:paddingLeft="3dip" android:paddingTop="3dip"
-        android:paddingRight="3dip" android:paddingBottom="0dip"
+        android:paddingStart="3dip" android:paddingTop="3dip"
+        android:paddingEnd="3dip" android:paddingBottom="0dip"
         android:src="@drawable/menuitem_checkbox" android:scaleType="fitCenter"
         android:layout_width="wrap_content" android:layout_height="wrap_content" />
 
     <TextView android:id="@+id/title"
-        android:paddingLeft="0dip" android:paddingTop="1dip"
-        android:paddingRight="0dip" android:paddingBottom="2dip"
+        android:paddingStart="0dip" android:paddingTop="1dip"
+        android:paddingEnd="0dip" android:paddingBottom="2dip"
         android:layout_width="wrap_content" android:layout_height="wrap_content"
         android:layout_weight="1" android:includeFontPadding="false" />
 
     <TextView android:id="@+id/shortcut"
-        android:paddingLeft="8dip" android:paddingTop="0dip"
-        android:paddingRight="0dip" android:paddingBottom="0dip"
+        android:paddingStart="8dip" android:paddingTop="0dip"
+        android:paddingEnd="0dip" android:paddingBottom="0dip"
         android:layout_width="20dip" android:layout_height="wrap_content"
         android:gravity="center_horizontal"  android:includeFontPadding="true"/>
 
diff --git a/core/res/res/layout/notification_action.xml b/core/res/res/layout/notification_action.xml
index 33cbab9..4e7c74c 100644
--- a/core/res/res/layout/notification_action.xml
+++ b/core/res/res/layout/notification_action.xml
@@ -20,9 +20,9 @@
     android:layout_width="0dp"
     android:layout_height="48dp"
     android:layout_weight="1"
-    android:gravity="left|center_vertical"
+    android:gravity="start|center_vertical"
     android:drawablePadding="8dp"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     android:textColor="#ccc"
     android:textSize="14dp"
     android:singleLine="true"
diff --git a/core/res/res/layout/notification_action_tombstone.xml b/core/res/res/layout/notification_action_tombstone.xml
index 992b37c..9977cfe 100644
--- a/core/res/res/layout/notification_action_tombstone.xml
+++ b/core/res/res/layout/notification_action_tombstone.xml
@@ -20,9 +20,9 @@
     android:layout_width="0dp"
     android:layout_height="48dp"
     android:layout_weight="1"
-    android:gravity="left|center_vertical"
+    android:gravity="start|center_vertical"
     android:drawablePadding="8dp"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     android:textColor="#ccc"
     android:textSize="14dp"
     android:singleLine="true"
diff --git a/core/res/res/layout/notification_intruder_content.xml b/core/res/res/layout/notification_intruder_content.xml
index 7f37032..ffd84d4 100644
--- a/core/res/res/layout/notification_intruder_content.xml
+++ b/core/res/res/layout/notification_intruder_content.xml
@@ -13,7 +13,7 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="40dp"
-        android:layout_marginLeft="40dp"
+        android:layout_marginStart="40dp"
         android:orientation="vertical"
         >
         <TextView android:id="@+id/title"
diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml
index 47bbbde..134f45e 100644
--- a/core/res/res/layout/notification_template_base.xml
+++ b/core/res/res/layout/notification_template_base.xml
@@ -33,10 +33,10 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingRight="8dp"
+        android:paddingEnd="8dp"
         android:paddingTop="2dp"
         android:paddingBottom="2dp"
         android:gravity="top"
@@ -46,7 +46,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingTop="6dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:orientation="horizontal"
             >
             <TextView android:id="@+id/title"
@@ -81,7 +81,7 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="-2dp"
             android:layout_marginBottom="-2dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:singleLine="true"
             android:fadingEdge="horizontal"
             android:ellipsize="marquee"
@@ -91,7 +91,7 @@
             android:id="@android:id/progress"
             android:layout_width="match_parent"
             android:layout_height="12dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:visibility="gone"
             style="?android:attr/progressBarStyleHorizontal"
             />
@@ -101,7 +101,7 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             >
             <TextView android:id="@+id/text"
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -121,14 +121,14 @@
                 android:layout_weight="0"
                 android:singleLine="true"
                 android:gravity="center"
-                android:paddingLeft="8dp"
+                android:paddingStart="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
                 android:layout_width="16dp"
                 android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
                 android:scaleType="centerInside"
                 android:visibility="gone"
                 android:drawableAlpha="153"
diff --git a/core/res/res/layout/notification_template_big_base.xml b/core/res/res/layout/notification_template_big_base.xml
index 69f0a24..b5da486 100644
--- a/core/res/res/layout/notification_template_big_base.xml
+++ b/core/res/res/layout/notification_template_big_base.xml
@@ -40,7 +40,7 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/notification_large_icon_width"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
             android:minHeight="@dimen/notification_large_icon_height"
             android:paddingTop="2dp"
             android:orientation="vertical"
@@ -50,8 +50,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:paddingTop="6dp"
-                android:layout_marginRight="8dp"
-                android:layout_marginLeft="8dp"
+                android:layout_marginEnd="8dp"
+                android:layout_marginStart="8dp"
                 android:orientation="horizontal"
                 >
                 <TextView android:id="@+id/title"
@@ -86,8 +86,8 @@
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
                 android:layout_marginBottom="-2dp"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:ellipsize="marquee"
@@ -97,8 +97,8 @@
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 />
@@ -106,8 +106,8 @@
                 android:id="@+id/line3"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:orientation="horizontal"
                 android:gravity="center_vertical"
                 >
@@ -129,14 +129,14 @@
                     android:layout_weight="0"
                     android:singleLine="true"
                     android:gravity="center"
-                    android:paddingLeft="8dp"
+                    android:paddingStart="8dp"
                     />
                 <ImageView android:id="@+id/right_icon"
                     android:layout_width="16dp"
                     android:layout_height="16dp"
                     android:layout_gravity="center"
                     android:layout_weight="0"
-                    android:layout_marginLeft="8dp"
+                    android:layout_marginStart="8dp"
                     android:scaleType="centerInside"
                     android:visibility="gone"
                     android:drawableAlpha="153"
@@ -147,8 +147,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="12dp"
                 android:layout_marginBottom="8dp"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:visibility="gone"
                 style="?android:attr/progressBarStyleHorizontal"
                 />
@@ -163,7 +163,7 @@
             layout="@layout/notification_action_list"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/notification_large_icon_width"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
             />
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_big_picture.xml b/core/res/res/layout/notification_template_big_picture.xml
index 172dfe5..f3f3951 100644
--- a/core/res/res/layout/notification_template_big_picture.xml
+++ b/core/res/res/layout/notification_template_big_picture.xml
@@ -46,7 +46,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="208dp"
-        android:paddingLeft="64dp"
+        android:paddingStart="64dp"
         android:layout_gravity="bottom"
         android:background="#CC111111"
         >
diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml
index 0b3386b..988a81f 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -32,7 +32,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:orientation="vertical"
         android:paddingTop="2dp"
         android:paddingBottom="2dp"
@@ -42,8 +42,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_weight="1"
             >
             <LinearLayout
@@ -87,7 +87,7 @@
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
                 android:layout_marginBottom="-2dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:ellipsize="marquee"
@@ -99,7 +99,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="12dp"
                 android:layout_marginBottom="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginEnd="8dp"
                 android:visibility="gone"
                 android:layout_weight="0"
                 style="?android:attr/progressBarStyleHorizontal"
@@ -109,7 +109,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="0dp"
                 android:layout_marginBottom="10dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 android:maxLines="8"
@@ -142,9 +142,9 @@
             android:id="@+id/line3"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:layout_marginBottom="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginEnd="8dp"
             android:orientation="horizontal"
             android:layout_weight="0"
             android:gravity="center_vertical"
@@ -167,14 +167,14 @@
                 android:layout_weight="0"
                 android:singleLine="true"
                 android:gravity="center"
-                android:paddingLeft="8dp"
+                android:paddingStart="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
                 android:layout_width="16dp"
                 android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
                 android:scaleType="centerInside"
                 android:visibility="gone"
                 android:drawableAlpha="153"
diff --git a/core/res/res/layout/notification_template_inbox.xml b/core/res/res/layout/notification_template_inbox.xml
index 8ee6263..6ebb443 100644
--- a/core/res/res/layout/notification_template_inbox.xml
+++ b/core/res/res/layout/notification_template_inbox.xml
@@ -33,7 +33,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
         android:paddingTop="2dp"
@@ -44,8 +44,8 @@
             android:id="@+id/line1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:paddingTop="6dp"
             android:orientation="horizontal"
             android:layout_weight="0"
@@ -82,8 +82,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="-2dp"
             android:layout_marginBottom="-2dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:fadingEdge="horizontal"
             android:ellipsize="marquee"
@@ -94,8 +94,8 @@
             android:id="@android:id/progress"
             android:layout_width="match_parent"
             android:layout_height="12dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:visibility="gone"
             android:layout_weight="0"
             style="?android:attr/progressBarStyleHorizontal"
@@ -104,8 +104,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -115,8 +115,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -126,8 +126,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -137,8 +137,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -148,7 +148,7 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -158,8 +158,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -169,8 +169,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -180,8 +180,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -212,9 +212,9 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:layout_marginBottom="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginEnd="8dp"
             android:orientation="horizontal"
             android:layout_weight="0"
             android:gravity="center_vertical"
@@ -237,14 +237,14 @@
                 android:layout_weight="0"
                 android:singleLine="true"
                 android:gravity="center"
-                android:paddingLeft="8dp"
+                android:paddingStart="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
                 android:layout_width="16dp"
                 android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
                 android:scaleType="centerInside"
                 android:visibility="gone"
                 android:drawableAlpha="153"
diff --git a/core/res/res/layout/notification_template_part_chronometer.xml b/core/res/res/layout/notification_template_part_chronometer.xml
index 382b0e4..aa9c4dc 100644
--- a/core/res/res/layout/notification_template_part_chronometer.xml
+++ b/core/res/res/layout/notification_template_part_chronometer.xml
@@ -22,5 +22,5 @@
     android:layout_weight="0"
     android:singleLine="true"
     android:gravity="center"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     />
diff --git a/core/res/res/layout/notification_template_part_time.xml b/core/res/res/layout/notification_template_part_time.xml
index 410fcaf..2bd6c3f 100644
--- a/core/res/res/layout/notification_template_part_time.xml
+++ b/core/res/res/layout/notification_template_part_time.xml
@@ -22,5 +22,5 @@
     android:layout_weight="0"
     android:singleLine="true"
     android:gravity="center"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     />
diff --git a/core/res/res/layout/permissions_account_and_authtokentype.xml b/core/res/res/layout/permissions_account_and_authtokentype.xml
index 833572603..ac5b08a 100644
--- a/core/res/res/layout/permissions_account_and_authtokentype.xml
+++ b/core/res/res/layout/permissions_account_and_authtokentype.xml
@@ -29,7 +29,7 @@
         android:layout_width="30dip"
         android:layout_height="30dip"
         android:drawable="@drawable/ic_bullet_key_permission"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:scaleType="fitCenter" />
 
 
@@ -37,8 +37,8 @@
         android:id="@+id/account_type"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/permission_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/permission_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -47,9 +47,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/account_type"
-        android:layout_toRightOf="@id/permission_icon"
+        android:layout_toEndOf="@id/permission_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -58,9 +58,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/account_name"
-        android:layout_toRightOf="@id/permission_icon"
+        android:layout_toEndOf="@id/permission_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/permissions_package_list_item.xml b/core/res/res/layout/permissions_package_list_item.xml
index 3c9570e..75ce0a7 100644
--- a/core/res/res/layout/permissions_package_list_item.xml
+++ b/core/res/res/layout/permissions_package_list_item.xml
@@ -28,7 +28,7 @@
         android:id="@+id/package_icon"
         android:layout_width="30dip"
         android:layout_height="30dip"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:src="@drawable/ic_text_dot"
         android:scaleType="fitCenter" />
 
@@ -37,8 +37,8 @@
         android:id="@+id/package_label"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/package_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/package_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 1a12c01..f67ed4e 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -18,7 +18,7 @@
     android:layout_width="match_parent"
     android:layout_height="?android:attr/dropdownListPreferredItemHeight"
     android:minWidth="196dip"
-    android:paddingRight="16dip">
+    android:paddingEnd="16dip">
     
     <!-- Icon will be inserted here. -->
     
@@ -28,7 +28,7 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="16dip"
+        android:layout_marginStart="16dip"
         android:duplicateParentState="true">
         
         <TextView 
@@ -36,7 +36,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
             android:singleLine="true"
             android:duplicateParentState="true"
@@ -48,7 +48,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/title"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmallPopupMenu"
             android:singleLine="true"
             android:duplicateParentState="true" />
diff --git a/core/res/res/layout/preference.xml b/core/res/res/layout/preference.xml
index 448f89a..824ca93 100644
--- a/core/res/res/layout/preference.xml
+++ b/core/res/res/layout/preference.xml
@@ -22,7 +22,7 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize"
+    android:paddingEnd="?android:attr/scrollbarSize"
     android:background="?android:attr/selectableItemBackground" >
 
     <ImageView
@@ -35,8 +35,8 @@
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="15dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -53,7 +53,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
diff --git a/core/res/res/layout/preference_category_holo.xml b/core/res/res/layout/preference_category_holo.xml
index 81e595c..f2c63ae 100644
--- a/core/res/res/layout/preference_category_holo.xml
+++ b/core/res/res/layout/preference_category_holo.xml
@@ -18,5 +18,5 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     style="?android:attr/listSeparatorTextViewStyle"
     android:id="@+android:id/title"
-    android:paddingLeft="@dimen/preference_item_padding_side"
-    android:paddingRight="@dimen/preference_item_padding_side" />
+    android:paddingStart="@dimen/preference_item_padding_side"
+    android:paddingEnd="@dimen/preference_item_padding_side" />
diff --git a/core/res/res/layout/preference_child.xml b/core/res/res/layout/preference_child.xml
index e9b50e0..6323c0e 100644
--- a/core/res/res/layout/preference_child.xml
+++ b/core/res/res/layout/preference_child.xml
@@ -20,8 +20,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="16dip"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -40,7 +40,7 @@
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginRight="6dip"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -57,7 +57,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
diff --git a/core/res/res/layout/preference_child_holo.xml b/core/res/res/layout/preference_child_holo.xml
index 4167862..17f97fd 100644
--- a/core/res/res/layout/preference_child_holo.xml
+++ b/core/res/res/layout/preference_child_holo.xml
@@ -20,8 +20,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="@dimen/preference_child_padding_side"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="@dimen/preference_child_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -34,14 +34,14 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:paddingEnd="@dimen/preference_item_padding_inner" />
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingRight="@dimen/preference_item_padding_inner"
+        android:paddingEnd="@dimen/preference_item_padding_inner"
         android:paddingTop="6dip"
         android:paddingBottom="6dip">
 
@@ -57,7 +57,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
diff --git a/core/res/res/layout/preference_header_item.xml b/core/res/res/layout/preference_header_item.xml
index a987de3..0d582a0 100644
--- a/core/res/res/layout/preference_header_item.xml
+++ b/core/res/res/layout/preference_header_item.xml
@@ -21,21 +21,21 @@
     android:minHeight="48dp"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <ImageView
         android:id="@+id/icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="6dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="6dip"
+        android:layout_marginEnd="6dip"
         android:layout_gravity="center" />
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -52,7 +52,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:ellipsize="end"
             android:maxLines="2" />
diff --git a/core/res/res/layout/preference_holo.xml b/core/res/res/layout/preference_holo.xml
index e574219..7a0a494 100644
--- a/core/res/res/layout/preference_holo.xml
+++ b/core/res/res/layout/preference_holo.xml
@@ -22,8 +22,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="@dimen/preference_item_padding_side"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="@dimen/preference_item_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -37,14 +37,15 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center"
             android:minWidth="48dp"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:paddingRight="@dimen/preference_item_padding_inner"
+             />
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingRight="@dimen/preference_item_padding_inner"
+        android:paddingEnd="@dimen/preference_item_padding_inner"
         android:paddingTop="6dip"
         android:paddingBottom="6dip">
 
@@ -60,7 +61,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
diff --git a/core/res/res/layout/preference_information.xml b/core/res/res/layout/preference_information.xml
index 32cbb90..e3be382 100644
--- a/core/res/res/layout/preference_information.xml
+++ b/core/res/res/layout/preference_information.xml
@@ -22,13 +22,13 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="16sp"
-        android:layout_marginRight="6sp"
+        android:layout_marginStart="16sp"
+        android:layout_marginEnd="6sp"
         android:layout_marginTop="6sp"
         android:layout_marginBottom="6sp"
         android:layout_weight="1">
@@ -44,7 +44,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="2" />
diff --git a/core/res/res/layout/preference_information_holo.xml b/core/res/res/layout/preference_information_holo.xml
index 5e03cfb..d0d446c 100644
--- a/core/res/res/layout/preference_information_holo.xml
+++ b/core/res/res/layout/preference_information_holo.xml
@@ -22,8 +22,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="@dimen/preference_item_padding_side"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="@dimen/preference_item_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -36,14 +36,14 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:paddingEnd="@dimen/preference_item_padding_inner" />
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingRight="@dimen/preference_item_padding_inner"
+        android:paddingEnd="@dimen/preference_item_padding_inner"
         android:paddingTop="6dip"
         android:paddingBottom="6dip">
 
@@ -58,7 +58,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 70bc59a..5812053 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -34,16 +34,16 @@
             android:orientation="vertical"
             android:layout_width="0px"
             android:layout_height="match_parent"
-            android:layout_marginRight="@dimen/preference_screen_side_margin_negative"
-            android:layout_marginLeft="@dimen/preference_screen_side_margin"
+            android:layout_marginEnd="@dimen/preference_screen_side_margin_negative"
+            android:layout_marginStart="@dimen/preference_screen_side_margin"
             android:layout_weight="@integer/preferences_left_pane_weight">
 
             <ListView android:id="@android:id/list"
                 android:layout_width="match_parent"
                 android:layout_height="0px"
                 android:layout_weight="1"
-                android:paddingLeft="@dimen/preference_screen_header_padding_side"
-                android:paddingRight="@dimen/preference_screen_header_padding_side"
+                android:paddingStart="@dimen/preference_screen_header_padding_side"
+                android:paddingEnd="@dimen/preference_screen_header_padding_side"
                 android:paddingTop="@dimen/preference_screen_header_vertical_padding"
                 android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
                 android:clipToPadding="false"
@@ -92,14 +92,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml
index 16afe13..726ce78 100644
--- a/core/res/res/layout/preference_list_content_single.xml
+++ b/core/res/res/layout/preference_list_content_single.xml
@@ -64,14 +64,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index fdef4fc..abfb1f2 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -30,8 +30,8 @@
         android:layout_weight="1"
         android:paddingTop="0dip"
         android:paddingBottom="@dimen/preference_fragment_padding_bottom"
-        android:paddingLeft="@dimen/preference_fragment_padding_side"
-        android:paddingRight="@dimen/preference_fragment_padding_side"
+        android:paddingStart="@dimen/preference_fragment_padding_side"
+        android:paddingEnd="@dimen/preference_fragment_padding_side"
         android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
         android:clipToPadding="false"
         android:drawSelectorOnTop="false"
@@ -55,14 +55,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout/preference_widget_seekbar.xml b/core/res/res/layout/preference_widget_seekbar.xml
index e4cf86d..c427965 100644
--- a/core/res/res/layout/preference_widget_seekbar.xml
+++ b/core/res/res/layout/preference_widget_seekbar.xml
@@ -22,7 +22,7 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -42,8 +42,8 @@
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="8dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="8dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -60,7 +60,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
@@ -70,7 +70,7 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_below="@android:id/summary"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:minWidth="@dimen/preference_widget_width"
             android:gravity="center"
             android:orientation="vertical" />
@@ -79,8 +79,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/summary"
-            android:layout_toRightOf="@android:id/widget_frame"
-            android:layout_alignParentRight="true" />
+            android:layout_toEndOf="@android:id/widget_frame"
+            android:layout_alignParentEnd="true" />
 
     </RelativeLayout>
 
diff --git a/core/res/res/layout/preferences.xml b/core/res/res/layout/preferences.xml
index f0c2535..c631f6c 100644
--- a/core/res/res/layout/preferences.xml
+++ b/core/res/res/layout/preferences.xml
@@ -19,7 +19,7 @@
 <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_marginRight="4dip"
+    android:layout_marginEnd="4dip"
     android:layout_gravity="center_vertical"
     android:background="@drawable/btn_circle"
     android:src="@drawable/ic_btn_round_more" />
diff --git a/core/res/res/layout/progress_dialog.xml b/core/res/res/layout/progress_dialog.xml
index 08e720f..0d3cd4a 100644
--- a/core/res/res/layout/progress_dialog.xml
+++ b/core/res/res/layout/progress_dialog.xml
@@ -27,9 +27,9 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:baselineAligned="false"
-        android:paddingLeft="8dip"
+        android:paddingStart="8dip"
         android:paddingTop="10dip"
-        android:paddingRight="8dip"
+        android:paddingEnd="8dip"
         android:paddingBottom="10dip">
 
         <ProgressBar android:id="@android:id/progress"
@@ -37,7 +37,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:max="10000"
-            android:layout_marginRight="12dip" />
+            android:layout_marginEnd="12dip" />
 
         <TextView android:id="@+id/message"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/progress_dialog_holo.xml b/core/res/res/layout/progress_dialog_holo.xml
index 9631efd..6aad9ea 100644
--- a/core/res/res/layout/progress_dialog_holo.xml
+++ b/core/res/res/layout/progress_dialog_holo.xml
@@ -33,7 +33,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:max="10000"
-            android:layout_marginRight="16dip" />
+            android:layout_marginEnd="16dip" />
 
         <TextView android:id="@+id/message"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 1d464aa..61cecae 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -33,8 +33,8 @@
               android:gravity="center"
               android:minLines="2"
               android:maxLines="2"
-              android:paddingLeft="4dip"
-              android:paddingRight="4dip" />
+              android:paddingStart="4dip"
+              android:paddingEnd="4dip" />
 
     <!-- Activity icon when presenting dialog
          Size will be filled in by ResolverActivity -->
@@ -51,7 +51,7 @@
               android:gravity="center"
               android:minLines="2"
               android:maxLines="2"
-              android:paddingLeft="4dip"
-              android:paddingRight="4dip" />
+              android:paddingStart="4dip"
+              android:paddingEnd="4dip" />
 </LinearLayout>
 
diff --git a/core/res/res/layout/resolver_grid.xml b/core/res/res/layout/resolver_grid.xml
index 4a0e84a..d271c1a 100644
--- a/core/res/res/layout/resolver_grid.xml
+++ b/core/res/res/layout/resolver_grid.xml
@@ -48,7 +48,7 @@
         android:measureWithLargestChild="true">
         <Button android:id="@+id/button_always"
                 android:layout_width="wrap_content"
-                android:layout_gravity="right"
+                android:layout_gravity="end"
                 android:layout_weight="1"
                 android:maxLines="2"
                 android:minHeight="@dimen/alert_dialog_button_bar_height"
@@ -60,7 +60,7 @@
                 android:onClick="onButtonClick" />
         <Button android:id="@+id/button_once"
                 android:layout_width="wrap_content"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 android:maxLines="2"
                 style="?android:attr/buttonBarButtonStyle"
diff --git a/core/res/res/layout/screen.xml b/core/res/res/layout/screen.xml
index 72f7392..902a797 100644
--- a/core/res/res/layout/screen.xml
+++ b/core/res/res/layout/screen.xml
@@ -41,8 +41,8 @@
         <ImageView android:id="@android:id/left_icon"
             android:layout_width="16dip"
             android:layout_height="16dip"
-            android:layout_marginRight="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginEnd="5dip"
+            android:layout_alignParentStart="true"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:scaleType="fitCenter"
@@ -50,13 +50,13 @@
         <LinearLayout android:id="@+android:id/right_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:layout_centerVertical="true"
         >
             <ImageView android:id="@android:id/right_icon"
                 android:layout_width="16dip"
                 android:layout_height="16dip"
-                android:layout_marginLeft="5dip"
+                android:layout_marginStart="5dip"
                 android:layout_gravity="center_vertical"
                 android:visibility="gone"
                 android:scaleType="fitCenter"
@@ -65,7 +65,7 @@
                 style="?android:attr/progressBarStyleSmallTitle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="5dip"
+                android:layout_marginStart="5dip"
                 android:layout_gravity="center_vertical"
                 android:visibility="gone"
                 android:max="10000"
@@ -75,9 +75,9 @@
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="2dip"
-            android:layout_toLeftOf="@android:id/right_container"
-            android:layout_toRightOf="@android:id/left_icon"
+            android:layout_marginStart="2dip"
+            android:layout_toStartOf="@android:id/right_container"
+            android:layout_toEndOf="@android:id/left_icon"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000"
@@ -90,8 +90,8 @@
             android:fadingEdge="horizontal"
             android:scrollHorizontally="true"
             android:gravity="center_vertical"
-            android:layout_toLeftOf="@android:id/right_container"
-            android:layout_toRightOf="@id/left_icon"
+            android:layout_toStartOf="@android:id/right_container"
+            android:layout_toEndOf="@id/left_icon"
         />
     </RelativeLayout>
 
diff --git a/core/res/res/layout/screen_progress.xml b/core/res/res/layout/screen_progress.xml
index c3f41fa..1f04d35 100644
--- a/core/res/res/layout/screen_progress.xml
+++ b/core/res/res/layout/screen_progress.xml
@@ -42,8 +42,8 @@
             style="?android:attr/progressBarStyleSmallTitle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="5dip"
-            android:layout_alignParentRight="true"
+            android:layout_marginStart="5dip"
+            android:layout_alignParentEnd="true"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000"
@@ -52,9 +52,9 @@
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="2dip"
-            android:layout_alignParentLeft="true"
-            android:layout_toLeftOf="@android:id/progress_circular"
+            android:layout_marginStart="2dip"
+            android:layout_alignParentStart="true"
+            android:layout_toStartOf="@android:id/progress_circular"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000" 
@@ -63,8 +63,8 @@
             style="?android:attr/windowTitleStyle"
             android:layout_width="match_parent" 
             android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:layout_toLeftOf="@android:id/progress_circular"
+            android:layout_alignParentStart="true"
+            android:layout_toStartOf="@android:id/progress_circular"
             android:background="@null"
             android:fadingEdge="horizontal"
             android:gravity="center_vertical"
diff --git a/core/res/res/layout/screen_title_icons.xml b/core/res/res/layout/screen_title_icons.xml
index 51d6a15..b866e57 100644
--- a/core/res/res/layout/screen_title_icons.xml
+++ b/core/res/res/layout/screen_title_icons.xml
@@ -36,19 +36,19 @@
         <!-- The title background has 9px left padding. -->
         <ImageView android:id="@android:id/left_icon"
             android:visibility="gone"
-            android:layout_marginRight="9dip"
+            android:layout_marginEnd="9dip"
             android:layout_width="16dip"
             android:layout_height="16dip"
             android:scaleType="fitCenter"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:layout_centerVertical="true" />
         <ProgressBar android:id="@+id/progress_circular"
             style="?android:attr/progressBarStyleSmallTitle"
             android:visibility="gone"
             android:max="10000"
             android:layout_centerVertical="true"
-            android:layout_alignParentRight="true"
-            android:layout_marginLeft="6dip"
+            android:layout_alignParentEnd="true"
+            android:layout_marginStart="6dip"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
         <!-- There are 6dip between this and the circular progress on the right, we
@@ -59,9 +59,9 @@
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="-3dip"
-            android:layout_toLeftOf="@android:id/progress_circular"
-            android:layout_toRightOf="@android:id/left_icon"
+            android:layout_marginStart="-3dip"
+            android:layout_toStartOf="@android:id/progress_circular"
+            android:layout_toEndOf="@android:id/left_icon"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000" />
@@ -69,8 +69,8 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="horizontal"
-            android:layout_toLeftOf="@id/progress_circular"
-            android:layout_toRightOf="@android:id/left_icon"
+            android:layout_toStartOf="@id/progress_circular"
+            android:layout_toEndOf="@android:id/left_icon"
             >
             <TextView android:id="@android:id/title"
                 style="?android:attr/windowTitleStyle"
@@ -81,7 +81,7 @@
                 android:fadingEdge="horizontal"
                 android:scrollHorizontally="true"
                 android:gravity="center_vertical"
-                android:layout_marginRight="2dip"
+                android:layout_marginEnd="2dip"
                 />
             <!-- 2dip between the icon and the title text, if icon is present. -->
             <ImageView android:id="@android:id/right_icon"
diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml
index acef2cc..730d606 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -19,8 +19,8 @@
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingLeft="@dimen/dropdownitem_text_padding_left"
-    android:paddingRight="4dip"
+    android:paddingStart="@dimen/dropdownitem_text_padding_left"
+    android:paddingEnd="4dip"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/searchResultListItemHeight" >
 
@@ -30,7 +30,7 @@
         android:layout_width="@dimen/dropdownitem_icon_width"
         android:layout_height="48dip"
         android:scaleType="centerInside"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
         android:visibility="invisible" />
@@ -39,7 +39,7 @@
         android:layout_width="48dip"
         android:layout_height="48dip"
         android:scaleType="centerInside"
-        android:layout_alignParentRight="true"
+        android:layout_alignParentEnd="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
         android:src="?attr/searchViewEditQuery"
@@ -51,7 +51,7 @@
         android:layout_height="48dip"
         android:scaleType="centerInside"
         android:layout_alignWithParentIfMissing="true"
-        android:layout_toLeftOf="@id/edit_query"
+        android:layout_toStartOf="@id/edit_query"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
         android:visibility="gone" />
@@ -67,8 +67,8 @@
         android:layout_height="29dip"
         android:paddingBottom="4dip"
         android:gravity="top"
-        android:layout_toRightOf="@android:id/icon1"
-        android:layout_toLeftOf="@android:id/icon2"
+        android:layout_toEndOf="@android:id/icon1"
+        android:layout_toStartOf="@android:id/icon2"
         android:layout_alignWithParentIfMissing="true"
         android:layout_alignParentBottom="true"
         android:visibility="gone" />
@@ -82,8 +82,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_centerVertical="true"
-        android:layout_toRightOf="@android:id/icon1"
-        android:layout_toLeftOf="@android:id/icon2"
+        android:layout_toEndOf="@android:id/icon1"
+        android:layout_toStartOf="@android:id/icon2"
         android:layout_above="@android:id/text2" />
 
 </RelativeLayout>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index ca1dc88..a281fcc 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -56,8 +56,8 @@
         android:layout_gravity="center_vertical"
         android:layout_marginTop="4dip"
         android:layout_marginBottom="4dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip"
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip"
         android:orientation="horizontal">
 
         <ImageView
@@ -65,7 +65,7 @@
             android:layout_width="@dimen/dropdownitem_icon_width"
             android:layout_height="wrap_content"
             android:scaleType="centerInside"
-            android:layout_marginLeft="@dimen/dropdownitem_text_padding_left"
+            android:layout_marginStart="@dimen/dropdownitem_text_padding_left"
             android:layout_gravity="center_vertical"
             android:src="?android:attr/searchViewSearchIcon"
             android:visibility="gone"
@@ -88,8 +88,8 @@
                 android:layout_weight="1"
                 android:minWidth="@dimen/search_view_text_min_width"
                 android:layout_gravity="bottom"
-                android:paddingLeft="@dimen/dropdownitem_text_padding_left"
-                android:paddingRight="@dimen/dropdownitem_text_padding_right"
+                android:paddingStart="@dimen/dropdownitem_text_padding_left"
+                android:paddingEnd="@dimen/dropdownitem_text_padding_right"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:background="@null"
@@ -106,8 +106,8 @@
                 android:id="@+id/search_close_btn"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:paddingLeft="8dip"
-                android:paddingRight="8dip"
+                android:paddingStart="8dip"
+                android:paddingEnd="8dip"
                 android:layout_gravity="center_vertical"
                 android:background="?android:attr/selectableItemBackground"
                 android:src="?android:attr/searchViewCloseIcon"
@@ -129,8 +129,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
                 android:background="?android:attr/selectableItemBackground"
                 android:src="?android:attr/searchViewGoIcon"
                 android:visibility="gone"
@@ -143,8 +143,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
                 android:src="?android:attr/searchViewVoiceIcon"
                 android:background="?android:attr/selectableItemBackground"
                 android:visibility="gone"
diff --git a/core/res/res/layout/select_dialog_item.xml b/core/res/res/layout/select_dialog_item.xml
index 96fdcc6..835c433 100644
--- a/core/res/res/layout/select_dialog_item.xml
+++ b/core/res/res/layout/select_dialog_item.xml
@@ -31,7 +31,7 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="14dip"
-    android:paddingRight="15dip"
+    android:paddingStart="14dip"
+    android:paddingEnd="15dip"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_item_holo.xml b/core/res/res/layout/select_dialog_item_holo.xml
index 3d19c06..62be406 100644
--- a/core/res/res/layout/select_dialog_item_holo.xml
+++ b/core/res/res/layout/select_dialog_item_holo.xml
@@ -30,7 +30,7 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_multichoice.xml b/core/res/res/layout/select_dialog_multichoice.xml
index a9be014..2dd83a3 100644
--- a/core/res/res/layout/select_dialog_multichoice.xml
+++ b/core/res/res/layout/select_dialog_multichoice.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="12dip"
-    android:paddingRight="7dip"
+    android:paddingStart="12dip"
+    android:paddingEnd="7dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_multichoice_holo.xml b/core/res/res/layout/select_dialog_multichoice_holo.xml
index 683151c..40125b7 100644
--- a/core/res/res/layout/select_dialog_multichoice_holo.xml
+++ b/core/res/res/layout/select_dialog_multichoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_singlechoice.xml b/core/res/res/layout/select_dialog_singlechoice.xml
index 1b9c973..1e18b44 100644
--- a/core/res/res/layout/select_dialog_singlechoice.xml
+++ b/core/res/res/layout/select_dialog_singlechoice.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="12dip"
-    android:paddingRight="7dip"
+    android:paddingStart="12dip"
+    android:paddingEnd="7dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_singlechoice_holo.xml b/core/res/res/layout/select_dialog_singlechoice_holo.xml
index 52782d0..545ec60 100644
--- a/core/res/res/layout/select_dialog_singlechoice_holo.xml
+++ b/core/res/res/layout/select_dialog_singlechoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/simple_dropdown_hint.xml b/core/res/res/layout/simple_dropdown_hint.xml
index df9d720..2583339 100644
--- a/core/res/res/layout/simple_dropdown_hint.xml
+++ b/core/res/res/layout/simple_dropdown_hint.xml
@@ -21,9 +21,9 @@
     android:id="@android:id/text1"
     android:textAppearance="?android:attr/dropDownHintAppearance"
     android:singleLine="true"
-    android:layout_marginLeft="3dip"
+    android:layout_marginStart="3dip"
     android:layout_marginTop="3dip"
-    android:layout_marginRight="3dip"
+    android:layout_marginEnd="3dip"
     android:layout_marginBottom="3dip"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />
diff --git a/core/res/res/layout/simple_dropdown_item_2line.xml b/core/res/res/layout/simple_dropdown_item_2line.xml
index d6f911a..c7093b4 100644
--- a/core/res/res/layout/simple_dropdown_item_2line.xml
+++ b/core/res/res/layout/simple_dropdown_item_2line.xml
@@ -51,7 +51,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/text1"
-            android:layout_alignLeft="@android:id/text1" />
+            android:layout_alignStart="@android:id/text1" />
     
     </TwoLineListItem>
 
diff --git a/core/res/res/layout/simple_expandable_list_item_1.xml b/core/res/res/layout/simple_expandable_list_item_1.xml
index df4324b..9810a60 100644
--- a/core/res/res/layout/simple_expandable_list_item_1.xml
+++ b/core/res/res/layout/simple_expandable_list_item_1.xml
@@ -18,7 +18,7 @@
     android:id="@android:id/text1"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeight"
-    android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
+    android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
     android:textAppearance="?android:attr/textAppearanceListItem"
     android:gravity="center_vertical"
 />
diff --git a/core/res/res/layout/simple_expandable_list_item_2.xml b/core/res/res/layout/simple_expandable_list_item_2.xml
index c0935fa..ed845f8 100644
--- a/core/res/res/layout/simple_expandable_list_item_2.xml
+++ b/core/res/res/layout/simple_expandable_list_item_2.xml
@@ -19,7 +19,7 @@
     android:layout_height="?android:attr/listPreferredItemHeight"
     android:paddingTop="2dip"
     android:paddingBottom="2dip"
-    android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
+    android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
     android:mode="twoLine"
 >
 
@@ -34,7 +34,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@android:id/text1"
-        android:layout_alignLeft="@android:id/text1"
+        android:layout_alignStart="@android:id/text1"
         android:textAppearance="?android:attr/textAppearanceSmall"
     />
 
diff --git a/core/res/res/layout/simple_list_item_1.xml b/core/res/res/layout/simple_list_item_1.xml
index c5e3efc..4249d10 100644
--- a/core/res/res/layout/simple_list_item_1.xml
+++ b/core/res/res/layout/simple_list_item_1.xml
@@ -20,7 +20,7 @@
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
 />
diff --git a/core/res/res/layout/simple_list_item_2.xml b/core/res/res/layout/simple_list_item_2.xml
index 9369876..8c6c9d3 100644
--- a/core/res/res/layout/simple_list_item_2.xml
+++ b/core/res/res/layout/simple_list_item_2.xml
@@ -24,7 +24,7 @@
 	<TextView android:id="@android:id/text1"
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
-    android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
     android:layout_marginTop="8dip"
 		android:textAppearance="?android:attr/textAppearanceListItem"
 	/>
@@ -33,7 +33,7 @@
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
 		android:layout_below="@android:id/text1"
-    android:layout_alignLeft="@android:id/text1"
+    android:layout_alignStart="@android:id/text1"
 		android:textAppearance="?android:attr/textAppearanceSmall"
 	/>
 
diff --git a/core/res/res/layout/simple_list_item_2_single_choice.xml b/core/res/res/layout/simple_list_item_2_single_choice.xml
index 90dfe37..5629567 100644
--- a/core/res/res/layout/simple_list_item_2_single_choice.xml
+++ b/core/res/res/layout/simple_list_item_2_single_choice.xml
@@ -19,8 +19,8 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="12dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="12dip"
     android:minHeight="?android:attr/listPreferredItemHeightSmall">
     <LinearLayout
         android:layout_width="wrap_content"
@@ -33,7 +33,7 @@
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="?android:attr/textColorAlertDialogListItem"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:singleLine="true"
             android:ellipsize="marquee"
         />
@@ -42,7 +42,7 @@
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorAlertDialogListItem"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:singleLine="true"
             android:ellipsize="marquee"
         />
@@ -51,7 +51,7 @@
         android:id="@+id/radio"
         android:layout_width="35dip"
         android:layout_height="wrap_content"
-        android:paddingRight="12dip"
+        android:paddingEnd="12dip"
         android:gravity="center_vertical"
         android:focusable="false"
         android:clickable="false"
diff --git a/core/res/res/layout/simple_list_item_activated_1.xml b/core/res/res/layout/simple_list_item_activated_1.xml
index a5fb5d1..41155e4 100644
--- a/core/res/res/layout/simple_list_item_activated_1.xml
+++ b/core/res/res/layout/simple_list_item_activated_1.xml
@@ -20,8 +20,8 @@
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
 />
diff --git a/core/res/res/layout/simple_list_item_activated_2.xml b/core/res/res/layout/simple_list_item_activated_2.xml
index 8746f6f..725697d 100644
--- a/core/res/res/layout/simple_list_item_activated_2.xml
+++ b/core/res/res/layout/simple_list_item_activated_2.xml
@@ -27,7 +27,7 @@
     <TextView android:id="@android:id/text1"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
+        android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
         android:layout_marginTop="6dip"
         android:textAppearance="?android:attr/textAppearanceListItem"
     />
@@ -36,7 +36,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@android:id/text1"
-        android:layout_alignLeft="@android:id/text1"
+        android:layout_alignStart="@android:id/text1"
         android:textAppearance="?android:attr/textAppearanceSmall"
     />
 
diff --git a/core/res/res/layout/simple_list_item_checked.xml b/core/res/res/layout/simple_list_item_checked.xml
index c9153f8..0c497d6 100644
--- a/core/res/res/layout/simple_list_item_checked.xml
+++ b/core/res/res/layout/simple_list_item_checked.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:checkMark="?android:attr/textCheckMark"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 />
diff --git a/core/res/res/layout/simple_list_item_multiple_choice.xml b/core/res/res/layout/simple_list_item_multiple_choice.xml
index cb23dfd..076d8c6 100644
--- a/core/res/res/layout/simple_list_item_multiple_choice.xml
+++ b/core/res/res/layout/simple_list_item_multiple_choice.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 />
diff --git a/core/res/res/layout/simple_list_item_single_choice.xml b/core/res/res/layout/simple_list_item_single_choice.xml
index 4a6cefa..4c1af09 100644
--- a/core/res/res/layout/simple_list_item_single_choice.xml
+++ b/core/res/res/layout/simple_list_item_single_choice.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 />
diff --git a/core/res/res/layout/simple_selectable_list_item.xml b/core/res/res/layout/simple_selectable_list_item.xml
index 6ce22d6..40f0ed6 100644
--- a/core/res/res/layout/simple_selectable_list_item.xml
+++ b/core/res/res/layout/simple_selectable_list_item.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItem"
     android:gravity="center_vertical"
     android:background="?android:attr/listChoiceBackgroundIndicator"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip"
 />
diff --git a/core/res/res/layout/ssl_certificate.xml b/core/res/res/layout/ssl_certificate.xml
index dd89a2d..a69d2a3 100644
--- a/core/res/res/layout/ssl_certificate.xml
+++ b/core/res/res/layout/ssl_certificate.xml
@@ -23,7 +23,7 @@
         android:id="@+id/body"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:gravity="start"
         android:orientation="vertical" >
 
         <!-- Placeholder for the success message or one or more warnings -->
@@ -43,8 +43,8 @@
             android:scaleType="fitXY"
             android:layout_weight="1"
             android:gravity="fill_horizontal"
-            android:layout_marginRight="20dip"
-            android:layout_marginLeft="20dip"/>
+            android:layout_marginEnd="20dip"
+            android:layout_marginStart="20dip"/>
 
         <!-- Issued to: -->
         <TextView
@@ -54,8 +54,8 @@
             android:text="@string/issued_to"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Common name: -->
@@ -64,15 +64,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/common_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/to_common"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organization: -->
@@ -81,15 +81,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/to_org"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organizational unit: -->
@@ -98,15 +98,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_unit"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/to_org_unit"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Serial number: -->
@@ -115,15 +115,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/serial_number"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/serial_number"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Issued by: -->
@@ -134,8 +134,8 @@
             android:text="@string/issued_by"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Common name: -->
@@ -144,15 +144,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/common_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/by_common"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organization: -->
@@ -161,15 +161,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/by_org"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organizational unit: -->
@@ -178,15 +178,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_unit"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/by_org_unit"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Validity Dates: -->
@@ -197,8 +197,8 @@
             android:text="@string/validity_period"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Issued On: -->
@@ -207,15 +207,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/issued_on"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/issued_on"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Expires On: -->
@@ -224,15 +224,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/expires_on"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/expires_on"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Fingerprints: -->
@@ -243,8 +243,8 @@
             android:text="@string/fingerprints"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- SHA-256 fingerprint: -->
@@ -253,15 +253,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/sha256_fingerprint"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/sha256_fingerprint"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- SHA-1 fingerprint: -->
@@ -270,15 +270,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/sha1_fingerprint"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/sha1_fingerprint"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
     </LinearLayout>
diff --git a/core/res/res/layout/tab_indicator.xml b/core/res/res/layout/tab_indicator.xml
index bc657c3..55ab1d8 100644
--- a/core/res/res/layout/tab_indicator.xml
+++ b/core/res/res/layout/tab_indicator.xml
@@ -18,8 +18,8 @@
     android:layout_width="0dip"
     android:layout_height="64dip"
     android:layout_weight="1"
-    android:layout_marginLeft="-3dip"
-    android:layout_marginRight="-3dip"
+    android:layout_marginStart="-3dip"
+    android:layout_marginEnd="-3dip"
     android:background="@android:drawable/tab_indicator">
 
     <ImageView android:id="@+id/icon"
diff --git a/core/res/res/layout/text_edit_action_popup_text.xml b/core/res/res/layout/text_edit_action_popup_text.xml
index 42e6f2e..16bf30e 100644
--- a/core/res/res/layout/text_edit_action_popup_text.xml
+++ b/core/res/res/layout/text_edit_action_popup_text.xml
@@ -17,8 +17,8 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:paddingTop="8dip"
     android:paddingBottom="8dip"
     android:gravity="center"
diff --git a/core/res/res/layout/text_edit_no_paste_window.xml b/core/res/res/layout/text_edit_no_paste_window.xml
index c4c0b8a..10a752c 100644
--- a/core/res/res/layout/text_edit_no_paste_window.xml
+++ b/core/res/res/layout/text_edit_no_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml
index adfe56b..3b8dbf2 100644
--- a/core/res/res/layout/text_edit_paste_window.xml
+++ b/core/res/res/layout/text_edit_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="12dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_side_no_paste_window.xml b/core/res/res/layout/text_edit_side_no_paste_window.xml
index 78423a7..aa695cd 100644
--- a/core/res/res/layout/text_edit_side_no_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_no_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml
index 37b774d..c947a19 100644
--- a/core/res/res/layout/text_edit_side_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index 1fdc1bf..a965ddd 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -17,11 +17,11 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
-          android:paddingLeft="16dip"
-          android:paddingRight="16dip"
+          android:paddingStart="16dip"
+          android:paddingEnd="16dip"
           android:paddingTop="8dip"
           android:paddingBottom="8dip"
-          android:layout_gravity="left|center_vertical"
+          android:layout_gravity="start|center_vertical"
           android:singleLine="true"
           android:drawablePadding="8dip"
           android:ellipsize="marquee"
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index df46db4..3958fc6 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -39,7 +39,7 @@
         android:id="@+id/minute"
         android:layout_width="70dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="5dip"
+        android:layout_marginStart="5dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -50,9 +50,9 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="43dip"
-        android:layout_marginLeft="5dip"
-        android:paddingLeft="20dip"
-        android:paddingRight="20dip"
+        android:layout_marginStart="5dip"
+        android:paddingStart="20dip"
+        android:paddingEnd="20dip"
         style="?android:attr/textAppearanceLargeInverse"
         android:textColor="@android:color/primary_text_light_nodisable"
         />
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 7b91022..765e71d 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -32,8 +32,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="6dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -54,8 +54,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
-        android:layout_marginLeft="6dip"
-        android:layout_marginRight="8dip"
+        android:layout_marginStart="6dip"
+        android:layout_marginEnd="8dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -67,8 +67,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="16dip"
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="16dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
diff --git a/core/res/res/layout/twelve_key_entry.xml b/core/res/res/layout/twelve_key_entry.xml
index 09c749d..7b41b50 100644
--- a/core/res/res/layout/twelve_key_entry.xml
+++ b/core/res/res/layout/twelve_key_entry.xml
@@ -24,16 +24,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/one"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -42,8 +42,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -52,8 +52,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -63,16 +63,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/four"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -81,8 +81,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -91,8 +91,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -101,16 +101,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/seven"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -119,8 +119,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -129,8 +129,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -140,16 +140,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/cancel"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textStyle="bold"
             android:text="@android:string/cancel"
@@ -159,8 +159,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -169,8 +169,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textStyle="bold"
             android:text="@android:string/ok"
diff --git a/core/res/res/layout/usb_storage_activity.xml b/core/res/res/layout/usb_storage_activity.xml
index 76c30fd..6dae0f9 100644
--- a/core/res/res/layout/usb_storage_activity.xml
+++ b/core/res/res/layout/usb_storage_activity.xml
@@ -44,16 +44,16 @@
         <Button android:id="@+id/mount_button" 
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="18dip"
-            android:paddingRight="18dip"
+            android:paddingStart="18dip"
+            android:paddingEnd="18dip"
             android:text="@string/usb_storage_button_mount"
             />
         <Button android:id="@+id/unmount_button"
             android:visibility="gone"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="18dip"
-            android:paddingRight="18dip"
+            android:paddingStart="18dip"
+            android:paddingEnd="18dip"
             android:text="@string/usb_storage_stop_button_mount"
             />
         <ProgressBar android:id="@+id/progress"
diff --git a/core/res/res/layout/volume_adjust_item.xml b/core/res/res/layout/volume_adjust_item.xml
index d3fa7e9..4a0fbaf 100644
--- a/core/res/res/layout/volume_adjust_item.xml
+++ b/core/res/res/layout/volume_adjust_item.xml
@@ -20,7 +20,7 @@
     android:orientation="horizontal"
     android:layout_marginTop="8dip"
     android:layout_marginBottom="8dip"
-    android:gravity="left|center_vertical">
+    android:gravity="start|center_vertical">
 
     <ImageView
         android:id="@+id/stream_icon"
@@ -37,6 +37,6 @@
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:padding="16dip"
-        android:layout_marginRight="16dip" />
+        android:layout_marginEnd="16dip" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/webview_find.xml b/core/res/res/layout/webview_find.xml
index a628ac8..da16043 100644
--- a/core/res/res/layout/webview_find.xml
+++ b/core/res/res/layout/webview_find.xml
@@ -27,7 +27,7 @@
         android:inputType="text"
         android:hint="@string/find_on_page"
         android:imeOptions="actionDone|flagNoExtractUi|flagNoFullscreen"
-        android:layout_marginRight="10dip"
+        android:layout_marginEnd="10dip"
         />
     <TextView android:id="@+id/matches"
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/wifi_p2p_dialog.xml b/core/res/res/layout/wifi_p2p_dialog.xml
index 8234187..86dcbfa 100644
--- a/core/res/res/layout/wifi_p2p_dialog.xml
+++ b/core/res/res/layout/wifi_p2p_dialog.xml
@@ -37,8 +37,10 @@
                     style="@style/wifi_item_label" />
 
                 <EditText android:id="@+id/wifi_p2p_wps_pin"
-                    android:inputType="textNoSuggestions"
-                    style="@style/wifi_item_content" />
+                        android:singleLine="true"
+                        android:maxLines="8"
+                        android:inputType="number"
+                        style="@style/wifi_item_content" />
             </LinearLayout>
         </LinearLayout>
     </LinearLayout>
diff --git a/core/res/res/layout/zoom_browser_accessory_buttons.xml b/core/res/res/layout/zoom_browser_accessory_buttons.xml
index 4bf2bdf..a264288 100644
--- a/core/res/res/layout/zoom_browser_accessory_buttons.xml
+++ b/core/res/res/layout/zoom_browser_accessory_buttons.xml
@@ -22,14 +22,14 @@
         android:background="@android:drawable/btn_browser_zoom_fit_page"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom|left"
-        android:layout_marginLeft="7dip"
+        android:layout_gravity="bottom|start"
+        android:layout_marginStart="7dip"
         />
     <ImageView android:id="@+id/zoom_page_overview" 
         android:background="@android:drawable/btn_browser_zoom_page_overview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom|right"
-        android:layout_marginRight="7dip"
+        android:layout_gravity="bottom|end"
+        android:layout_marginEnd="7dip"
         />
 </merge>
diff --git a/core/res/res/layout/zoom_magnify.xml b/core/res/res/layout/zoom_magnify.xml
index 374819e..562257c 100644
--- a/core/res/res/layout/zoom_magnify.xml
+++ b/core/res/res/layout/zoom_magnify.xml
@@ -26,8 +26,8 @@
         />
     <ImageView android:id="@+id/zoomMagnify"
         android:focusable="true"
-        android:layout_gravity="bottom|right"
-        android:paddingRight="2dip"
+        android:layout_gravity="bottom|end"
+        android:paddingEnd="2dip"
         android:src="@drawable/btn_zoom_page"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 29c23e9..476f7b0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Laat die program toe om die interne status van die stelsel op te haal. Kwaadwillige programme kan \'n verskeidenheid privaat en beveiligde inligting ophaal wat hulle gewoonlik nooit nodig het nie."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"haal skerminhoud op"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Laat die program toe om die inhoud van die aktiewe venster op te haal. Kwaadwillige programme kan die hele venster se inhoud ophaal, en al die teks ondersoek, behalwe wagwoorde."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"haal vensterinligting op"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Laat \'n program toe om inligting oor vensters vanaf die vensterbestuurder op te haal. Kwaadwillige programme kan moontlik inligting ophaal wat vir interne stelselgebruik bedoel is."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filter gebeure"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Laat \'n program toe om \'n invoerfilter te registreer wat die stroom van alle gebruikergebeure filter voordat dit versend word. Kwaadwillige programme kan moontlik die stelsel-UI beheer sonder gebruikers se tussentrede."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelike afskakeling"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Plaas die aktiwiteitbestuurder in \'n afsluitingstatus. Doen nie \'n volledige afsluiting nie."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"verhoed program-oorskakelings"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopieer URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Kies teks"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekskeuse"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"voeg by woordeboek"</string>
-    <string name="deleteText" msgid="7070985395199629156">"vee uit"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Voeg by woordeboek"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Vee uit"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Invoermetode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksaksies"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Bergingspasie word min"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; stuur \'n groot aantal SMS-boodskappe. Wil jy hierdie program toelaat om voort te gaan om boodskappe te stuur?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Laat toe"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Weier"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Stuur SMS na kortkode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Stuur \'n premium-SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag \'n SMS stuur aan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, wat lyk asof dit \'n SMS-kortkode is.&lt;p&gt;Die stuur van SMS\'e na sommige kortkodes kan veroorsaak dat jou selfoonrekening gedebiteer word vir premiumdienste.&lt;p&gt;Wil jy hierdie program toelaat om die boodskap te stuur?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag \'n SMS stuur aan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, wat \'n betaalde SMS-kortkode is.&lt;p&gt;&lt;b&gt;As jy \'n boodskap na hierdie bestemming stuur, sal jou selfoonrekening gedebiteer word vir betaalde dienste.&lt;/b&gt;&lt;p&gt;Wil jy hierdie program toelaat om die boodskap te stuur?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Stuur boodskap"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Moenie stuur nie"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Gee kwaadwillige program aan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart verwyder"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Die mobielnetwerk sal nie beskikbaar wees nie totdat jy weer begin met \'n geldige SIM-kaart."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Klaar"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f0e96ba..0a490eb 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"የስርዓቱን ውስጣዊ ሁናቴ ለመበርበር ለመተግበሪያው ይፈቅዳሉ፡፡ በተለምዶ የማያስፈልጋቸውን ብዙ አይነት የግል እና የደህንነት መረጃዎችን ተንኮል አዘል  መተግበሪያዎች ሊበረብሩ ይችላሉ፡፡"</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"የማያ ይዘት ሰርስረህ አውጣ"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"የነቃ መስኮት ይዘትን ለመበርበር ለመተግበሪያው ይፈቅዳሉ፡፡ ጠቅላላውን የመስኮት ይዘት ለመበርበር እና ከይለፍ ቃል በስተቀር ሁሉንም ጽሑፉን ለማየት ጎጂ መተግበሪያዎች ይችላሉ፡፡"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"የመስኮት መረጃን አምጣ"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"አንድ መተግበሪያ ከመስኮት አቀናባሪው ሆኖ ስለመስኮቱ መረጃ እንዲያመጣ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ለውስጣዊ ስርዓት ጥቅም የታሰበ መረጃን ሊወስዱ ይችላሉ።"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"ክስተቶችን አጣራ"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"አንድ መተግበሪያ የሁሉንም ተጠቃሚዎች ክስተቶች ከመላካቸው በፊት እነሱን የሚያጣራ የግቤት ማጣሪያ እንዲመዘግብ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ተጠቃሚው ጣልቃ ሳይገባ የስርዓቱን በይነገጽ ሊቆጣጠሩት ይችላሉ።"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"የURL ቅጂ"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"ፅሁፍ ምረጥ"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"የፅሁፍ ምርጫ"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"ወደ መዝገበ ቃላት አክል"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ሰርዝ"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"ወደ መዝገበ ቃላት አክል"</string>
+    <string name="deleteText" msgid="6979668428458199034">"ሰርዝ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"ግቤት ሜተድ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"የፅሁፍ እርምጃዎች"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"የማከማቻ ቦታ እያለቀ ነው"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ቁጥራቸው ብዙ የሆኑ የኤስ.ኤም.ኤስ. መልዕክቶችን እየላከ ነው። ይሄ መተግበሪያ መልዕክቶችን መላኩን እንዲቀጥል መፍቀድ ትፈልጋለህ?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"ፍቀድ"</string>
     <string name="sms_control_no" msgid="625438561395534982">"ከልክል"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"ኤስ.ኤም.ኤስ. ለአጭር ኮድ ይላክ?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"ከፍ ያለ ኤስ.ኤም.ኤስ. ይላክ?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የጽሑፍ መልዕክት ለ&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; መላክ ይፈልጋል፣ ይሄ ደግሞ የኤስ.ኤም.ኤስ. አጭር ኮድ ሆኖ ተገኝቷል።&lt;p&gt;የጽሑፍ መልዕክቶች ለሆኑ አጭር ኮዶች መላክ የተንቀሳቃሽ መለያህ ከፍ ላሉ አገልግሎቶች ሊያስከፍለው ይችላል።&lt;p&gt;ይሄ መተግበሪያ መልዕክቱ እንዲልክ መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የጽሑፍ መልዕክት ለ&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; መላክ ይፈልጋል፣ ይሄ ደግሞ ከፍ ያለ የኤስ.ኤም.ኤስ. አጭር ኮድ ነው።&lt;p&gt;&lt;b&gt;መልዕክት ወደዚህ ቦታ መላክ የተንቀሳቃሽ መለያህ ከፍ ላሉ አገልግሎቶች ያስከፍለዋል።&lt;/b&gt;&lt;p&gt;ይሄ መተግበሪያ መልዕክቱ እንዲልክ መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"መልዕክት ላክ"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"አትላክ"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"ተንኮል አዘል መተግበሪያ ሪፖርት አድርግ"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM ካርድ ተወግዷል"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"በትክክል የገባ SIM ካርድ ድጋሚ እስኪያስጀምሩ የተንቀሳቃሽ ስልክ አውታረመረብ አይገኝም።"</string>
     <string name="sim_done_button" msgid="827949989369963775">"ተከናውኗል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7a9ad77..cae9a5b 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"للسماح للتطبيق باسترداد الحالة الداخلية للنظام. قد تسترد التطبيقات الضارة مجموعة كبيرة من المعلومات الخاصة والآمنة التي لا حاجة لها في العادة على الإطلاق."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"استرداد محتوى الشاشة"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"للسماح للتطبيق باسترداد محتوى النافذة النشطة. يمكن للبرامج الضارة استرداد محتوى النافذة بالكامل وفحص جميع النصوص الموجودة بها باستثناء كلمات المرور."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"استرداد معلومات النوافذ"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"للسماح لأحد التطبيقات باستعادة معلومات حول النوافذ من مدير النوافذ. يمكن أن تستعيد التطبيقات الضارة معلومات الغرض منها استخدام النظام الداخلي."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"تصفية الأحداث"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"للسماح لأحد التطبيقات بتسجيل فلتر إدخال يعمل على تصفية مجموعة البث من جميع أحداث المستخدمين قبل إرسالها. يمكن أن يتحكم برنامج ضار في واجهة المستخدم النظام دون تدخل المستخدم."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"نسخ عنوان URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"تحديد نص"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"تحديد النص"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"إضافة إلى القاموس"</string>
-    <string name="deleteText" msgid="7070985395199629156">"حذف"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"إضافة إلى القاموس"</string>
+    <string name="deleteText" msgid="6979668428458199034">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"طريقة الإرسال"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"إجراءات النص"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"مساحة التخزين منخفضة"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; يرسل عددًا كبيرًا من الرسائل القصيرة SMS. هل تريد السماح لهذا التطبيق بالاستمرار في إرسال الرسائل؟"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"السماح"</string>
     <string name="sms_control_no" msgid="625438561395534982">"رفض"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"إرسال رسالة SMS إلى رمز قصير؟"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"هل تريد إرسال رسالة قصيرة SMS مميزة؟"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; يريد إرسال رسالة نصية إلى &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;، والذي يُعد رمزًا قصيرًا لرسالة قصيرة SMS.&lt;p&gt;قد يؤدي إرسال رسائل نصية إلى بعض الرموز القصيرة إلى تحصيل رسوم من حساب جوالك للخدمات المميزة.&lt;p&gt;هل تريد السماح لهذا التطبيق بإرسال الرسالة؟"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; يريد إرسال رسالة نصية إلى &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;، والذي يُعد رمزًا قصيرًا لرسالة قصيرة SMS مميزة.&lt;p&gt;&lt;b&gt;سيؤدي إرسال رسالة إلى هذه الوجهة إلى تحصيل رسوم من حساب جوالك للخدمات المميزة.&lt;/b&gt;&lt;p&gt;هل تريد السماح لهذا التطبيق بإرسال الرسالة؟"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"إرسال رسالة"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"عدم الإرسال"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"الإبلاغ عن تطبيق ضار"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"تمت إزالة بطاقة SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"لن تكون شبكة الجوال متاحة حتى تتم إعادة التشغيل وإدخال بطاقة SIM صالحة."</string>
     <string name="sim_done_button" msgid="827949989369963775">"تم"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 21f8896..1f7c043 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Дазваляе прыкладанням атрымліваць інфармацыю аб унутраным стане сістэмы. Шкоднасныя прыкладанні могуць атрымліваць шырокі спектр прыватных дадзеных і дадзеных, прызначаных для забеспячэння бяспекі інфармацыі, якія звычайна ім не патрэбны."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"атрыманне зместу экрана"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дазваляе прыкладанням атрымліваць змесціва актыўнага акна. Шкоднасныя прыкладанні могуць атрымліваць усё змесціва акна і разглядаць увесь яго тэкст, акрамя пароляў."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"атрымаць звесткi пра акно"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Дазваляе прыкладанням вымаць iнфармацыю пра вокны з iнструмента кiравання вокнамi. Шкоднасныя прыкладаннi могуць вымаць iнфармацыю, якая прызначана для ўнутранага выкарыстання ў сiстэме."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"фільтр падзей"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Дазваляе прыкладанню рэгiстраваць фiльтр уводу, якi перадае паток усiх дзеянняў карыстальнiка, перш чым будуць адпраўленыя звесткi пра iх. Шкоднасныя прыкладаннi могуць кантраляваць iнтэрфейс без умяшальнiцтва."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частковае адключэнне"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Спыняе дзейнасць менеджэра. Не выконвае поўнае адключэнне."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"прадухіляць пераключэнне прыкладанняў"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Скапіяваць URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Выбраць тэкст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Вылучэнне тэксту"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"дадаць у слоўнік"</string>
-    <string name="deleteText" msgid="7070985395199629156">"выдаліць"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Дадаць у слоўнік"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Выдалiць"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метад уводу"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Дзеянні з тэкстам"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Месца для захавання на зыходзе"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Прыкладанне &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; дасылае вялікую колькасць SMS-паведамленняў. Дазволіць гэтаму прыкладанню працягваць адпраўляць паведамленні?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Дазволіць"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Забараніць"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Адправiць SMS на кароткі нумар?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Адправiць платнае SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Прыкладанне &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt спрабуе адправiць тэкставае паведамленне на нумар &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, які, здаецца, з\'яўляецца кароткім нумарам для SMS.&lt;p&gt;Дасыланне тэкставых паведамленняў на кароткія нумары можа прывесці да спісання сродкаў з вашага мабільнага рахунку за платныя паслугі.&lt;/b&gt;&lt;p&gt;Жадаеце дазволіць гэтаму прыкладанню даслаць паведамленне?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Прыкладанне &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;g спрабуе адправiць тэкставае паведамленне на нумар &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, які з\'яўляецца платным кароткім нумарам для SMS.&lt;p&gt;&lt;b&gt;Адпраўка паведамлення гэтаму атрымальніку прывядзе да спісання сродкаў з вашага мабільнага рахунку за платныя паслугі.&lt;/b&gt;&lt;p&gt;Жадаеце дазволіць гэтаму прыкладанню даслаць паведамленне?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Адправiць паведамленне"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не адпраўляць"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Павед. аб шкодн. прыкладаннях"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта выдаленая"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мабільная сетка будзе недаступная да перазагрузкі з дзеючай SIM-картай."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Гатова"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 8d45aa9..0645d78 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Разрешава на приложението да извлича вътрешното състояние на системата. Злонамерените приложения могат да извлекат разнообразна частна и защитена информация, която нормално не би трябвало да им е нужна."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"извличане на съдържанието на екрана"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Разрешава на приложението да извлича съдържанието от активния прозорец. Злонамерените приложения могат да извлекат цялото му съдържание и да проследят целия текст в него освен паролите."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"извличане на информация за прозорците"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Разрешава на приложението да извлича информация за прозорците от съответния мениджър. Злонамерените приложения може да извличат данни, които са предназначени за вътрешно използване от системата."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"филтриране на събитията"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешава на приложението да регистрира входящ филтър, който филтрира потока на всички потребителски събития преди изпращането им. Злонамерено приложение може да контролира системния потребителски интерфейс без намесата на потребителя."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частично изключване"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копиране на URL адреса"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Избор на текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Избиране на текст"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"добавяне към речника"</string>
-    <string name="deleteText" msgid="7070985395199629156">"изтриване"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Добавяне в речника"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Изтриване"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод на въвеждане"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Действия с текста"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Мястото в хранилището е на изчерпване"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; изпраща голям брой SMS съобщения. Искате ли да разрешите на това приложение да продължи да го прави?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Разрешаване"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Отказване"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Да се изпрати ли SMS до кратък код?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Да се изпрати ли импулсен SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; иска да изпрати текстово съобщение до &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, което изглежда е кратък код на SMS.&lt;p&gt;Изпращането на съобщения до някои такива кодове може да доведе до таксуване на мобилната ви сметка за услуги, които се плащат допълнително.&lt;p&gt;Искате ли да разрешите на това приложение да изпрати съобщението?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; иска да изпрати текстово съобщение до &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, което е кратък код за импулсен SMS.&lt;p&gt;&lt;b&gt;Изпращането до тази точка ще доведе до таксуване на мобилната ви сметка за услуги, които се плащат допълнително.&lt;/b&gt;&lt;p&gt;Искате ли да разрешите на това приложение да изпрати съобщението?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Изпращане на съобщението"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Да не се изпраща"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Сигнал за злонам. приложение"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM картата е премахната"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Няма да имате достъп до мобилната мрежа, докато не рестартирате с поставена валидна SIM карта."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 711030c..95f8944 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permet que l\'aplicació recuperi l\'estat intern del sistema. Les aplicacions malicioses poden recuperar una àmplia gamma d\'informació privada i de seguretat que normalment no haurien de necessitar mai."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperació del contingut de la pantalla"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet que l\'aplicació recuperi el contingut de la finestra activa. Les aplicacions malicioses poden recuperar el contingut de tota la finestra i examinar-ne tot el text, excepte les contrasenyes."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupera informació de les finestres"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet que una aplicació recuperi informació sobre les finestres del gestor de finestres. Aplicacions malicioses podrien recuperar informació dirigida a la utilització per part del sistema intern."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtra els esdeveniments"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet que una aplicació registri un filtre d\'entrada per a l\'emissió de tots els esdeveniments d\'usuari abans no s\'enviïn. Aplicacions malicioses podrien controlar la IU del sistema sense la intervenció de l\'usuari."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"apagar parcialment"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Posa el gestor d\'activitats en estat d\'apagada. No fa una apagada completa."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copia l\'URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selecciona el text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecció de text"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"afegeix al diccionari"</string>
-    <string name="deleteText" msgid="7070985395199629156">"suprimeix"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Afegeix al diccionari"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Suprimeix"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mètode d\'entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"S\'està acabant l\'espai d\'emmagatzematge"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; està enviant molts missatges SMS. Vols permetre que aquesta aplicació continuï enviant missatges?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permet"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Denega"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Vols enviar SMS a codi curt?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vols enviar el SMS prèmium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge de text a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que sembla que és un codi SMS curt.&lt;p&gt;Si envies missatges de text a codis curts, pot ser que es carreguin serveis prèmium al teu compte mòbil.&lt;p&gt;Vols permetre que aquesta aplicació enviï el missatge?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge de text a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que és un codi curt SMS prèmium.&lt;p&gt;&lt;b&gt;Si envies un missatge a aquesta destinació, es carregaran els serveis prèmium al teu compte mòbil.&lt;/b&gt;&lt;p&gt;Vols permetre que aquesta aplicació enviï el missatge?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Envia el missatge"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviïs"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Informa d\'una aplic. maliciosa"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Extracció de la targeta SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La xarxa de telefonia mòbil no estarà disponible fins que no reiniciïs amb una targeta SIM vàlida inserida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fet"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c026ecd..190eb62 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Umožňuje aplikaci získat informace o vnitřním stavu systému. Škodlivé aplikace mohou získat různé soukromé informace nebo informace o zabezpečení, které by běžně vůbec neměly potřebovat."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"načtení obsahu obrazovky"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikaci načíst obsah aktivního okna. Škodlivé aplikace mohou načíst obsah celého okna a prozkoumat všechen text kromě hesel."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítání informací o oknech"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikaci načíst informace o oknech ze správce oken. Škodlivé aplikace mnohou načíst informace, které slouží k internímu systémovému využití."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrování událostí"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožní aplikaci registrovat vstupní filtr, který filtruje stream všech uživatelských přenosů před jejich odvysíláním. Škodlivé aplikace mohou používat uživatelské rozhraní systému bez zásahu uživatele."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"částečné vypnutí"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvede správce činností do vypnutého stavu. Nedojde však k úplnému vypnutí."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabránění přepínání aplikací"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopírovat adresu URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Vybrat text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Výběr textu"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"přidat do slovníku"</string>
-    <string name="deleteText" msgid="7070985395199629156">"smazat"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Přidat do slovníku"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Smazat"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metoda zadávání dat"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operace s textem"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"V úložišti je málo místa"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;odesílá velký počet SMS zpráv. Chcete aplikaci povolit, aby zprávy odesílala i nadále?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Povolit"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odmítnout"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Odeslat SMS?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Odeslat zprávu Premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Aplikace&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odeslat zprávu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, což je zřejmě číslo služby SMS.&lt;p&gt;Za odesílání zpráv na určitá čísla mohou být na mobilní účet naúčtovány poplatky za prémiové služby.&lt;p&gt;Chcete aplikaci povolit odeslání zprávy?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce poslat zprávu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, což je číslo služby Premium SMS.&lt;p&gt;&lt;b&gt;Pokud zprávu odešlete na toto číslo, budou vám na mobilní účet naúčtovány poplatky za prémiové služby.&lt;/b&gt;&lt;p&gt;Chcete aplikaci povolit odeslání zprávy?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Odeslat zprávu"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Neodesílat"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Nahlásit škodlivou aplikaci"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM karta odebrána"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilní síť bude dostupná až poté, co vložíte platnou SIM kartu a restartujete zařízení."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 443f828..89f2e1e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Tillader, at appen kan hente systemets interne tilstand. Ondsindede apps kan hente en lang række fortrolige og beskyttede oplysninger, som de normalt aldrig ville have brug for."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hente skærmindhold"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillader, at appen kan hente indholdet i det aktive vindue. Ondsindede apps kan hente al indholdet i vinduet og undersøge al dens tekst med undtagelse af adgangskoder."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hent oplysninger om vinduer"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Tillader, at en applikation henter oplysninger om vinduerne i vinduesadministratoren. Skadelige apps kan muligvis hente oplysninger, der er beregnet til intern systembrug."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer begivenheder"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Tillader, at en applikation registrerer et inputfilter, som filtrerer alle brugeres strøm, før disse afsendes. Skadelige apps kan muligvis kontrollere systemets grænseflade uden brugerens deltagelse."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delvis lukning"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Sætter aktivitetsadministratoren i lukningstilstand. Lukker ikke helt ned."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"undgå programskift"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopier webadresse"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Markér tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstmarkering"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"føj til ordbog"</string>
-    <string name="deleteText" msgid="7070985395199629156">"slet"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Føj til ordbog"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Slet"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Inputmetode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Der er snart ikke mere lagerplads"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sender et stort antal sms-beskeder. Vil du tillade, at denne app fortsat sender beskeder?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Tillad"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Afvis"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Send sms til shortcode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vil du sende en premium-sms?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil du sende en sms til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som ser ud til at være en premium-sms-shortcode.&amp;.&lt;p&gt;Hvis du sender en sms til nogle shortcodes, kan det medføre, at din mobilkonto bliver debiteret for premium-tjenester.&lt;p&gt;Vil du tillade, at denne app sender beskeden?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil du sende en sms til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som er en premium-sms-shortcode.&lt;p&gt;&lt;b&gt;Hvis du sender en besked til denne destination, bliver din mobilkonto debiteret for premium-tjenester.&lt;/b&gt;&lt;p&gt;Vil du tillade, at denne app sender beskeden?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send besked"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Send ikke"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rapportér ondsindet app"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort blev fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile netværk er utilgængeligt, indtil du genstarter med et gyldigt SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Afslut"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 8707f28..02017c4 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Ermöglicht der App, den internen Systemstatus abzurufen. Schädliche Apps können so eine Vielzahl an privaten und geschützten Daten abrufen, die sie in der Regel nicht benötigen."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Bildschirminhalt abrufen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ermöglicht der App, den Inhalt des aktiven Fensters abzurufen. Schädliche Apps können so den gesamten Fensterinhalt abrufen und mit Ausnahme von Passwörtern den gesamten Text auswerten."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Fensterinformationen abrufen"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ermöglicht einer App, Informationen über die Fenster vom Fenster-Manager abzurufen. Schädliche Apps können Informationen abrufen, die für die systeminterne Nutzung gedacht sind."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"Ereignisse filtern"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ermöglicht einer App, einen Eingabefilter zu registrieren, der den Stream aller Nutzerereignisse vor ihrem Versand filtert. Eine schädliche App kann die System-UI ohne Eingriff des Nutzers kontrollieren."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partielles Herunterfahren"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL kopieren"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Text auswählen"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Textauswahl"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"Zum Wörterbuch hinzufügen"</string>
-    <string name="deleteText" msgid="7070985395199629156">"Löschen"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Zum Wörterbuch hinzufügen"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Löschen"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Eingabemethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textaktionen"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Der Speicherplatz wird knapp"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sendet eine große Anzahl SMS. Möchten Sie zulassen, dass die App weiterhin Nachrichten sendet?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Zulassen"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nicht zulassen"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"SMS an Kurzwahl senden?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Premium-SMS senden?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; versucht, eine SMS an &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; zu senden. Dabei scheint es sich um eine SMS-Kurzwahl zu handeln.&lt;p&gt;Wenn Sie SMS an eine Kurzwahl senden, werden Ihnen für Ihr Mobilfunkkonto möglicherweise Premiumdienste in Rechnung gestellt.&lt;p&gt;Möchten Sie zulassen, dass die App die Nachricht sendet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; versucht, eine SMS an die Premium-SMS-Kurzwahl &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; zu senden.&lt;p&gt;&lt;b&gt;Wenn Sie eine Nachricht an diese Zieladresse senden, werden Ihnen für Ihr Mobilfunkkonto Premiumdienste in Rechnung gestellt.&lt;/b&gt;&lt;p&gt;Möchten Sie zulassen, dass die App die Nachricht sendet?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Nachricht senden"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nicht senden"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Schädliche App melden"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-Karte entfernt"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Das Mobilfunknetz ist erst wieder verfügbar, wenn Sie einen Neustart mit einer gültigen SIM-Karte durchführen."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fertig"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 223e096..3116317 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Επιτρέπει στην  εφαρμογή την ανάκτηση της εσωτερικής κατάστασης του συστήματος. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν μεγάλη ποικιλία ιδιωτικών πληροφοριών και πληροφοριών ασφάλειας οι οποίες δεν θα έπρεπε να τους είναι απαραίτητες υπό φυσιολογικές συνθήκες."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ανάκτηση περιεχομένου οθόνης"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Επιτρέπει στην εφαρμογή την ανάκτηση του περιεχομένου του ενεργού παραθύρου. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν ολόκληρο το περιεχόμενο του παραθύρου και να εξετάσουν ολόκληρο το κείμενό του εκτός από τους κωδικούς πρόσβασης."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ανάκτηση πληροφοριών παραθύρων"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Επιτρέπει σε μια εφαρμογή να ανακτήσει πληροφορίες σχετικά με τα παράθυρα από το διαχειριστή παραθύρων. Οι κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν πληροφορίες που προορίζονται για την εσωτερική χρήση του συστήματος."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"φιλτράρισμα συμβάντων"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Επιτρέπει σε μια εφαρμογή να καταγράφει ένα φίλτρο εισαγωγής, το οποίο φιλτράρει τη ροή όλων των συμβάντων χρήστη πριν την αποστολή τους. Μια κακόβουλη εφαρμογή μπορεί να ελέγξει τη διεπαφή του συστήματος χωρίς την παρέμβαση του χρήστη."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"μερικός τερματισμός λειτουργίας"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Θέτει το πρόγραμμα διαχείρισης δραστηριοτήτων σε κατάσταση τερματισμού λειτουργιών. Δεν εκτελεί πλήρη τερματισμό λειτουργιών."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτροπή εναλλαγών εφαρμογών"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Αντιγραφή διεύθυνσης URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Επιλογή κειμένου"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Επιλογή κειμένου"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"προσθήκη στο λεξικό"</string>
-    <string name="deleteText" msgid="7070985395199629156">"διαγραφή"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Προσθήκη στο λεξικό"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Διαγραφή"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Μέθοδος εισόδου"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ενέργειες κειμένου"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ο χώρος αποθήκευσης εξαντλείται"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; στέλνει έναν μεγάλο αριθμό μηνυμάτων SMS. Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να συνεχίσει να στέλνει μηνύματα;"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Αποδοχή"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Άρνηση"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Να αποσταλεί SMS στον κωδικό;"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Να σταλεί SMS ειδικής χρέωσης;"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ζητά την έγκρισή σας για την αποστολή μηνύματος κειμένου στον αριθμό &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ο οποίος φαίνεται ότι είναι κωδικός για την αποστολή SMS με ειδική χρέωση.&lt;p&gt;Η αποστολή μηνύματος σε αυτόν τον αριθμό θα χρεωθεί στον λογαριασμό του κινητού σας ως παροχή υπηρεσιών.&lt;p&gt;Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να στείλει το μήνυμα;"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; θέλει να στείλει ένα μήνυμα κειμένου στον αριθμό &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ο οποίος είναι ένας κωδικός αποστολής SMS με ειδική χρέωση.&lt;p&gt;&lt;b&gt;Η αποστολή μηνύματος σε αυτόν τον αριθμό θα χρεωθεί στον λογαριασμό του κινητού σας ως παροχή υπηρεσιών.&lt;/b&gt;&lt;p&gt;Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να στείλει το μήνυμα;"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Αποστολή μηνύματος"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Να μην αποσταλεί"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Αναφορά κακόβουλης εφαρμογής"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Η κάρτα SIM αφαιρέθηκε"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Το δίκτυο κινητής τηλεφωνίας δεν θα είναι διαθέσιμο μέχρι να κάνετε επανεκκίνηση αφού τοποθετήσετε μια έγκυρη κάρτα SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Τέλος"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index cdacbc4..e6e85ed 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Allows the app to retrieve the internal state of the system. Malicious apps may retrieve a wide variety of private and secure information that they should never normally need."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"retrieve screen content"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Allows the app to retrieve the content of the active window. Malicious apps may retrieve the entire window content and examine all its text except passwords."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"retrieve window info"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Allows an application to retrieve information about the windows from the window manager. Malicious apps may retrieve information that is intended for internal system usage."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filter events"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Allows an application to register an input filter which filters the stream of all user events before they are dispatched. Malicious app may control the system UI without user intervention."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Puts the activity manager into a shut-down state. Does not perform a complete shut down."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copy URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Select text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Text selection"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"add to dictionary"</string>
-    <string name="deleteText" msgid="7070985395199629156">"delete"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Add to dictionary"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Delete"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Input method"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Text actions"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Storage space running out"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; is sending a large number of SMS messages. Do you want to allow this app to continue sending messages?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Allow"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Deny"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Send SMS to short code?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Send premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a text message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, which appears to be an SMS short code.&lt;p&gt;Sending text messages to some short codes may cause your mobile account to be billed for premium services.&lt;p&gt;do you want to allow this app to send the message?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a text message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, which is a premium SMS short code.&lt;p&gt;&lt;b&gt;Sending a message to this destination will cause your mobile account to be billed for premium services.&lt;/b&gt;&lt;p&gt;Do you want to allow this app to send the message?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send message"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Don\'t send"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Report malicious app"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Done"</string>
@@ -1283,7 +1294,7 @@
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string>
-    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phones"</string>
+    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string>
     <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3b39f2a..b1cf6bd 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones maliciosas pueden recuperar una amplia variedad de información privada y segura que normalmente no necesitarían."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar contenido de la pantalla"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones maliciosas pueden recuperar el contenido completo de la ventana y examinar todo el texto, excepto las contraseñas."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar información de ventanas"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que una aplicación recupere la información del administrador de ventanas relacionada con estas. Las aplicaciones maliciosas pueden recuperar información destinada al uso interno del sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre la transmisión de todos los eventos del usuario antes de ser enviados. Las aplicaciones maliciosas pueden controlar la IU del sistema sin la intervención del usuario."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Pone al administrador de la actividad en estado de cierre. No realiza un cierre completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir conmutadores de aplicación"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Seleccionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selección de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"Agregar al diccionario"</string>
-    <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Agregar al diccionario"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio de almacenamiento"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; está enviando una gran cantidad de mensajes SMS. ¿Quieres permitir que está aplicación siga enviando mensajes?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Rechazar"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"¿Enviar SMS premium?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"¿Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, y parece que se trata de un SMS premium.&lt;p&gt;Al enviar mensajes de texto a estos números, es posible que se facturen servicios premium en tu cuenta móvil.&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, y se trata de un SMS premium.&lt;p&gt;&lt;b&gt;Al enviar un mensaje a este destino, se podrán facturar servicios premium en tu cuenta móvil.&lt;/b&gt;&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensaje"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Notificar aplicación malintencionada"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La red para celulares no estará disponible hasta que reinicies, luego de insertar una tarjeta SIM válida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Finalizado"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0118067..c765056 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones malintencionadas pueden usar este permiso para recuperar una gran variedad de información protegida y privada que normalmente no deberían necesitar."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar contenido de la pantalla"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones malintencionadas pueden recuperar todo el contenido de la ventana y analizar todo el texto de la misma, excepto las contraseñas."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar información de ventanas"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que una aplicación recupere información sobre las ventanas del administrador de ventanas. Las aplicaciones malintencionadas pueden recuperar información destinada al uso interno del sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre el flujo de los eventos del usuario antes de que se envíe. Las aplicaciones malintencionadas pueden controlar la interfaz del sistema sin la intervención del usuario."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Pone el administrador de actividades en estado de cierre. No realiza un cierre completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar cambios de aplicación"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Seleccionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selección de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"añadir al diccionario"</string>
-    <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Añadir al diccionario"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada de texto"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; está enviando un gran número de mensajes SMS. ¿Quieres permitir que está aplicación siga enviando mensajes?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Denegar"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"¿Enviar SMS premium?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"¿Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; y parece que se trata de un SMS premium.&lt;p&gt;Al enviar mensajes de texto a estos números, es posible que se facturen servicios premium en tu cuenta móvil.&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; y se trata de un SMS premium.&lt;p&gt;&lt;b&gt;Al enviar un mensaje a este destino, se podrán facturar servicios premium en tu cuenta móvil.&lt;/b&gt;&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensaje"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Notificar aplicación malintencionada"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La red móvil no estará disponible hasta que reinicies el dispositivo con una tarjeta SIM válida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Listo"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c887a41..4228f28 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Võimaldab rakendusel teada saada süsteemi sisemist olekut. Pahatahtlikud rakendused võivad hankida mitmesugust privaatset ja turvateavet, mida neil tavaliselt kunagi vaja ei lähe."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ekraanisisu taastamine"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Võimaldab rakendusel kätte saada aktiivse akna sisu. Pahatahtlikud rakendused võivad hankida kogu akna sisu ja uurida kogu selle teksti, välja arvatud paroole."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hangi akna teave"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Võimaldab rakendusel hankida teavet aknahalduri akende kohta. Pahatahtlikud rakendused võivad hankida teavet, mis on mõeldud süsteemisiseseks kasutamiseks."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtreeri sündmused"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Võimaldab rakendusel registreerida sisestusfiltri, mis filtreerib kõigi kasutaja sündmuste voo, enne kui need ära saadetakse. Pahatahtlik rakendus võib süsteemi kasutajaliidest juhtida ilma kasutaja sekkumiseta."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"osaline väljalülitamine"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lülitab tegevushalduri väljalülitusolekusse. Ei lülita lõplikult välja."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"väldi rakenduste ümberlülitamist"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopeeri URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Valige tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksti valimine"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"lisa sõnastikku"</string>
-    <string name="deleteText" msgid="7070985395199629156">"kustuta"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Lisa sõnastikku"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Kustuta"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Sisestusmeetod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoimingud"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Talletusruum saab täis"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; saadab suurel hulgal SMS-sõnumeid. Kas tahate lubada sellel rakendusel ka edaspidi sõnumeid saata?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Luba"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Keela"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Kas saata SMS lühinumbrile?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Kas saata tasuline SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tahab saata tekstsõnumi adressaadile &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, mis paistab olevat SMS-i lühinumber.&lt;p&gt;Mõnele lühinumbrile saadetud sõnumi eest võidakse teie mobiilikontole esitada arve tasuliste teenuste eest.&lt;p&gt;Kas lubate rakendusel selle sõnumi saata?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tahab saata tekstsõnumi adressaadile &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, mis on tasulise SMS-i lühinumber.&lt;p&gt;&lt;b&gt;Kui saadate sõnumi sellele adressaadile, esitatakse teie mobiilikontole arve tasuliste teenuste eest.&lt;/b&gt;&lt;p&gt;Kas lubate rakendusel sõnumi saata?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Saada sõnum"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ära saada"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Teata pahatahtlikust rakend."</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart eemaldatud"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobiilsidevõrk ei ole saadaval, kuni sisestate kehtiva SIM-kaardi ja taaskäivitate seadme."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f52ab95..e497489 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -44,7 +44,7 @@
     <string name="passwordIncorrect" msgid="7612208839450128715">"رمز ورود اشتباه است."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI کامل شد."</string>
     <string name="badPin" msgid="9015277645546710014">"پین قدیمی که نوشته‎اید صحیح نیست."</string>
-    <string name="badPuk" msgid="5487257647081132201">"PUK که نوشته اید صحیح نیست."</string>
+    <string name="badPuk" msgid="5487257647081132201">"PUK که نوشته‌اید صحیح نیست."</string>
     <string name="mismatchPin" msgid="609379054496863419">"پین‎هایی که وارد کرده‎اید با یکدیگر مطابقت ندارند."</string>
     <string name="invalidPin" msgid="3850018445187475377">"یک پین بنویسید که 4 تا 8 رقم باشد."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با 8 رقم یا بیشتر تایپ کنید."</string>
@@ -129,10 +129,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"همگام سازی"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگام سازی"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"تعداد موارد حذف شده <xliff:g id="CONTENT_TYPE">%s</xliff:g> بسیار زیاد است."</string>
-    <string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانه لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
+    <string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانهٔ لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"حافظه تلفن پر است. بعضی از فایل‌ها را حذف کنید تا فضا آزاد شود."</string>
     <string name="me" msgid="6545696007631404292">"من"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینه‌های رایانه لوحی"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینه‌های رایانهٔ لوحی"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"گزینه‌های تلفن"</string>
     <string name="silent_mode" msgid="7167703389802618663">"حالت ساکت"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"روشن کردن بی سیم"</string>
@@ -143,14 +143,14 @@
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"زنگ لرزشی"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"زنگ روشن"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"خاموش کردن..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانه لوحی شما خاموش می‌شود."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش می‌شود."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"گوشی شما خاموش می‌شود."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"آیا می‎خواهید تلفن خاموش شود؟"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"راه‌اندازی مجدد در حالت امن"</string>
-    <string name="reboot_safemode_confirm" msgid="55293944502784668">"آیا می‌خواهید با حالت امن راه‌اندازی مجدد کنید؟ با این کار کلیه برنامه‌های شخص ثالثی که نصب کرده‌اید غیرفعال می‌شوند. با راه‌اندازی دوباره سیستم این برنامه‌ها دوباره بازیابی می‌شوند."</string>
+    <string name="reboot_safemode_confirm" msgid="55293944502784668">"آیا می‌خواهید با حالت امن راه‌اندازی مجدد کنید؟ با این کار همهٔ برنامه‌های شخص ثالثی که نصب کرده‌اید غیرفعال می‌شوند. با راه‌اندازی دوباره سیستم این برنامه‌ها دوباره بازیابی می‌شوند."</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"اخیر"</string>
     <string name="no_recent_tasks" msgid="8794906658732193473">"برنامه‎های جدید موجود نیست."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"گزینه‌های رایانه لوحی"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"گزینه‌های رایانهٔ لوحی"</string>
     <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>
@@ -168,7 +168,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"پیام‌های شما"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"پیام کوتاه، ایمیل و دیگر پیام‌ها را بخوانید."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"اطلاعات شخصی شما"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در رایانه لوحی."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در رایانهٔ لوحی."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در گوشی."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"موقعیت مکانی شما"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"بر موقعیت مکانی فیزیکی خود نظارت داشته باشید."</string>
@@ -176,8 +176,8 @@
     <string name="permgroupdesc_network" msgid="4478299413241861987">"به ویژگی‎های مختلف شبکه دسترسی داشته باشید."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"حساب‌های شما"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"به حساب‌های موجود دسترسی داشته باشید."</string>
-    <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"کنترل‌های سخت افزار"</string>
-    <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"دسترسی مستقیم به سخت افزار در گوشی."</string>
+    <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"کنترل‌های سخت‌افزار"</string>
+    <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"دسترسی مستقیم به سخت‌افزار در گوشی."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"تماس‌های تلفنی"</string>
     <string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"نظارت، ضبط و پردازش تماس‌های تلفنی."</string>
     <string name="permgrouplab_systemTools" msgid="4652191644082714048">"ابزارهای سیستم"</string>
@@ -208,10 +208,10 @@
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"ارسال پیامک بدون تأیید"</string>
     <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"به برنامه اجازه می‌دهد پیامک‌ها را ارسال کند. این باعث ایجاد هزینه‌های پیش‌بینی نشده می‌شود. برنامه‌های مخرب ممکن است با ارسال پیام بدون تأیید شما هزینه‌هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"خواندن پیام‌های نوشتاری شما (پیامک یا MMS)"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در رایانه لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آن‌ها بخواند."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در رایانهٔ لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آن‌ها بخواند."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در تلفن یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آن‌ها بخواند."</string>
     <string name="permlab_writeSms" msgid="3216950472636214774">"ویرایش پیام‌های نوشتاری شما (پیامک یا MMS)"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"به برنامه اجازه می‎دهد تا در پیام‌های کوتاه ذخیره شده در رایانه لوحی یا سیم کارت بنویسد. برنامه‎های مخرب پیام‌های شما را حذف می‎کنند."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"به برنامه اجازه می‎دهد تا در پیام‌های کوتاه ذخیره شده در رایانهٔ لوحی یا سیم کارت بنویسد. برنامه‎های مخرب پیام‌های شما را حذف می‎کنند."</string>
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"به برنامه اجازه می‎دهد تا در پیام‌های کوتاه ذخیره شده در تلفن یا سیم کارت بنویسد. برنامه‎های مخرب می‎توانند پیام‌های شما را حذف کنند."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"دریافت پیام‌های نوشتاری (WAP)"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"به برنامه اجازه می‌دهد پیام‌های WAP را دریافت و پردازش کند. این مجوز می‌تواند پیام‌های ارسالی به شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
@@ -226,7 +226,7 @@
     <string name="permlab_startAnyActivity" msgid="2918768238045206456">"شروع هر نوع فعالیت"</string>
     <string name="permdesc_startAnyActivity" msgid="997823695343584001">"به برنامه اجازه می‎دهد هر فعالیتی را شروع کند بدون اینکه وضعیت صادرشده یا حفاظت با مجوز در نظر گرفته شود."</string>
     <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"تنظیم سازگاری با صفحهٔ نمایش"</string>
-    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"به برنامه کاربردی اجازه کنترل حالت سازگاری صفحهٔ نمایش برای برنامه‌های دیگر را می‌دهد. برنامه‌های خرابکار ممکن است باعث کارکرد نادرست دیگر برنامه‌ها شوند."</string>
+    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"به برنامهٔ کاربردی اجازه کنترل حالت سازگاری صفحهٔ نمایش برای برنامه‌های دیگر را می‌دهد. برنامه‌های خرابکار ممکن است باعث کارکرد نادرست دیگر برنامه‌ها شوند."</string>
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"فعال کردن عیب‌یابی برنامه"</string>
     <string name="permdesc_setDebugApp" msgid="4474512416299013256">"به برنامه اجازه می‎دهد تا عیب‌یابی را برای برنامه‌ای دیگر فعال کند. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا اجرای برنامه‎های دیگر را متوقف کنند."</string>
     <string name="permlab_changeConfiguration" msgid="4162092185124234480">"تغییر تنظیمات نمایشگر سیستم"</string>
@@ -243,24 +243,28 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"به برنامه اجازه می‎دهد تا وضعیت داخلی سیستم را بازیابی کند. برنامه‎های مخرب می‎توانند انواع مختلفی از اطلاعات خصوصی و امن را که معمولا به آن‌ها نیاز ندارند، بازیابی کنند."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"بازیابی محتوای صفحه"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"به برنامه اجازه می‎دهد تا محتوای پنجره فعال را بازیابی کند. برنامه‎های مخرب می‎توانند کل محتوای پنجره را بازیابی کنند و همه متن آنرا به غیر از گذرواژه‎ها امتحان کنند."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"بازیابی اطلاعات پنجره"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"به یک برنامه کاربردی اجازه می‌دهد که اطلاعات مربوط به پنجره‌ها را از مدیریت پنجره بازیابی کند. برنامه‌های کاربردی مخرب ممکن است اطلاعاتی که برای استفاده سیستم داخلی درنظر گرفته شده‌اند را بازیابی کنند."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"فیلتر کردن رویدادها"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"به یک برنامه کاربردی اجازه می‌دهد یک فیلتر ورودی را که جریان تمام رویدادهای کاربران را قبل از ارسال شدن فیلتر می‌کند، ثبت نماید. برنامه‌ کاربردی مخرب ممکن است رابط کاربری سیستم را بدون مداخله کاربر، کنترل کند."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"خاموش شدن جزئی"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"مدیر فعالیت را در حالت خاموشی قرار می‌دهد. خاموشی را به صورت کامل انجام نمی‌دهد."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"اجازه نمی‎دهد کاربر به برنامه دیگری برود."</string>
-    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"نظارت و کنترل راه اندازی همه برنامه"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"به برنامه اجازه می‎دهد تا نحوه راه اندازی فعالیت‌های سیستم را کنترل کند. برنامه‎های مخرب می‎توانند کاملا با سیستم سازگار شوند. این مجوز فقط برای توسعه نیاز است و برای استفاده عادی نیست."</string>
+    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"نظارت و کنترل راه‌اندازی همه برنامه"</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"به برنامه اجازه می‎دهد تا نحوه راه‌اندازی فعالیت‌های سیستم را کنترل کند. برنامه‎های مخرب می‎توانند کاملا با سیستم سازگار شوند. این مجوز فقط برای توسعه نیاز است و برای استفاده عادی نیست."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ارسال پخش بسته حذف شده"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"به برنامه اجازه می‎دهد تا اعلان حذف بسته برنامه را پخش کند. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا هر برنامه در حال اجرای دیگر را از بین ببرد."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ارسال پخش دریافت شده توسط پیامک"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"به برنامه اجازه می‎دهد تا اعلان دریافت پیام کوتاه را پخش کند. برنامه‎های مخرب می‎توانند از این برای جعل پیام‌های کوتاه ورودی استفاده کنند."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ارسال پخش دریافت شده توسط WAP-PUSH"</string>
-    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"به برنامه اجازه می‎دهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحه وب را با انواع مخرب جایگزین کنند."</string>
+    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"به برنامه اجازه می‎دهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحهٔ وب را با انواع مخرب جایگزین کنند."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"محدود کردن تعداد فرآیندهای در حال اجرا"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"به برنامه اجازه می‎دهد تا حداکثر تعداد پردازشهایی را که اجرا خواهد شد کنترل کند. هرگز برای برنامه‎های عادی لازم نیست."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"بستن اجباری برنامه‌های پس‌زمینه"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"به برنامه اجازه می‎دهد تا به محض اینکه فعالیتها به پس‌زمینه رفتند تمام شوند. برای برنامه‎های عادی نیازی نیست."</string>
     <string name="permlab_batteryStats" msgid="7863923071360031652">"اصلاح کردن آمار مربوط به باتری"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"به برنامه اجازه می‎دهد تا آمار جمع آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
+    <string name="permdesc_batteryStats" msgid="6835186932305744068">"به برنامه اجازه می‎دهد تا آمار جمع‌آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_backup" msgid="470013022865453920">"کنترل نسخهٔ پشتیبان سیستم و بازیابی"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"به برنامه اجازه می‎دهد پشتیبان سیستم را کنترل کند و مکانیستم را بازیابی کند. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"تهیه نسخهٔ پشتیبان کامل را تأیید کرده یا عملیات را بازیابی کنید"</string>
@@ -274,7 +278,7 @@
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"مدیریت نشانه‎های برنامه"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"به برنامه اجازه می‎دهد با ایجاد کنارگذر از سفارش عادی Z، نشانه‎های خود را ایجاد و مدیریت کند. برای برنامه‎های عادی مورد نیاز است."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"کلیدها و دکمه‌های کنترل را فشار دهید"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"به برنامه اجازه می‎دهد تا رویدادهای ورودی خود (فشردن کلیدها و غیره) را تحویل دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا کارکرد رایانه لوحی را کنترل کنند."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"به برنامه اجازه می‎دهد تا رویدادهای ورودی خود (فشردن کلیدها و غیره) را تحویل دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا کارکرد رایانهٔ لوحی را کنترل کنند."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"به برنامه اجازه می‎دهد تا رویدادهای ورودی خود را به برنامه‎های دیگر تحویل دهد (فشردن کلیدها و غیره). برنامه‎های مخرب می‎توانند از آن برای کنترل کارکرد تلفن استفاده کنند."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"مواردی که می‌نویسید و کارهایی که انجام می‌دهید را ضبط کنید"</string>
     <string name="permdesc_readInputState" msgid="8387754901688728043">"به برنامه اجازه می‎دهد تا کلیدهایی را که هنگام تعامل با برنامهٔ دیگر فشار می‎دهید ببیند (مانند تایپ کردن گذرواژه). برای برنامه‎های عادی مورد نیاز نیست."</string>
@@ -296,42 +300,42 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"به برنامه اجازه می‎دهد تا چرخش صفحه را هر وقت بخواهد تغییر دهد. برای برنامه‎های عادی نیاز نیست."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغییر سرعت اشاره‌گر"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"به برنامه اجازه می‎دهد تا سرعت ماوس و پد کنترل را هر وقت خواست تغییر دهد. برای برنامه‎های عادی نیاز نیست."</string>
-    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحه کلید"</string>
-    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه می‌دهد تا چیدمان صفحه کلید را تغییر دهد. این کار هیچ‌گاه برای برنامه‌های عادی نیاز نیست."</string>
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحه‌کلید"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه می‌دهد تا چیدمان صفحه‌کلید را تغییر دهد. این کار هیچ‌گاه برای برنامه‌های عادی نیاز نیست."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ارسال سیگنالهای Linux به برنامه‎ها"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"به برنامه اجازه می‎دهد تا درخواست کند سیگنال ارائه شده به همه مراحل دائم ارسال شود."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"همیشه برنامه اجرا شود"</string>
-    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی رایانه لوحی می‌شود."</string>
+    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی رایانهٔ لوحی می‌شود."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی تلفن می‌شود."</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"حذف برنامه‎ها"</string>
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"به برنامه اجازه می‎دهد تا بسته‎های Android را پاک کند. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا برنامه‎های مهم را حذف کنند."</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"حذف داده‎های برنامه‎های دیگر"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"به برنامه اجازه می‎دهد تا داده‎های کاربر را پاک کند."</string>
-    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"حذف حافظه پنهان برنامه‎های دیگر"</string>
-    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"به برنامه اجازه می‎دهد تا فایل‌های حافظه پنهان را پاک کند."</string>
+    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"حذف حافظهٔ پنهان برنامه‎های دیگر"</string>
+    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"به برنامه اجازه می‎دهد تا فایل‌های حافظهٔ پنهان را پاک کند."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"اندازه گیری فضای حافظه برنامه"</string>
-    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"به برنامه اجازه می‎دهد تا کدها، داده‎ها و اندازه‎های حافظه پنهان خود را بازیابی کند"</string>
+    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"به برنامه اجازه می‎دهد تا کدها، داده‎ها و اندازه‎های حافظهٔ پنهان خود را بازیابی کند"</string>
     <string name="permlab_installPackages" msgid="2199128482820306924">"نصب مستقیم برنامه"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"به برنامه اجازه می‎دهد تا بسته‎های Android به روز شده یا جدید را نصب کند. برنامه‎های مخرب می‎توانند از این استفاده کنند تا برنامه‎های جدید را با مجوزهای قوی اختیاری اضافه کنند."</string>
-    <string name="permlab_clearAppCache" msgid="7487279391723526815">"حذف تمام داده‎های حافظه پنهان برنامه"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"به برنامه اجازه می‎دهد تا حافظه رایانه لوحی را با حذف فایل‌ها در فهرست حافظه پنهان برنامه آزاد کند. معمولا دسترسی برای پردازش سیستم بسیار محدود است."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"به برنامه اجازه می‎دهد تا با حذف فایل‌ها در فهرست حافظه پنهان برنامه حافظه تلفن را آزاد کند. معمولا دسترسی به پردازش سیستم بسیار محدود است."</string>
+    <string name="permlab_clearAppCache" msgid="7487279391723526815">"حذف تمام داده‎های حافظهٔ پنهان برنامه"</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"به برنامه اجازه می‎دهد تا حافظه رایانهٔ لوحی را با حذف فایل‌ها در فهرست حافظهٔ پنهان برنامه آزاد کند. معمولا دسترسی برای پردازش سیستم بسیار محدود است."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"به برنامه اجازه می‎دهد تا با حذف فایل‌ها در فهرست حافظهٔ پنهان برنامه حافظه تلفن را آزاد کند. معمولا دسترسی به پردازش سیستم بسیار محدود است."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"انتقال منابع برنامه"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"به برنامه اجازه می‎دهد تا منابع برنامه را از رسانه داخلی به رسانه خارجی و بالعکس منتقل کند."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"مطالعه داده‌های گزارش حساس"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"به برنامه اجازه می‎دهد فایل‌های مختلف گزارش سیستم را بخواند. با این کار، برنامه اطلاعات کلی مربوط به کاری که با رایانه لوحی انجام می‎دهید را کشف می‌کند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"به برنامه اجازه می‎دهد فایل‌های مختلف گزارش سیستم را بخواند. با این کار، برنامه اطلاعات کلی مربوط به کاری که با رایانهٔ لوحی انجام می‎دهید را کشف می‌کند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string>
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"به برنامه اجازه می‎دهد تا فایل‌های گزارش مختلف سیستم را بخواند. این کار به برنامه اجازه می‎دهد اطلاعات عمومی کاری که با تلفن انجام می‎دهید مثلا اطلاعات خصوصی و شخصی را کشف کند."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"استفاده از هر رمزگشای رسانه‎ای برای بازپخش"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"اجازه می‎دهد برنامه از هر رمزگشای رسانه نصب شده‌ای استفاده کند تا برای پخش رمزگشایی شود."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"خواندن/نوشتن منابع متعلق به تشخیص"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"به برنامه اجازه می‌دهد هر منبعی را که متعلق به گروه تشخیص است بخواند و در آن بنویسد؛ به‌عنوان مثال، فایل‌های /dev. این امر به‌صورت بالقوه می‌تواند بر پایدار بودن و امنیت سیستم تأثیر بگذارد. این تنها باید برای تشخیص‎‌های مختص سخت‌افزار توسط تولیدکننده یا اپراتور استفاده شود."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"فعال یا غیر فعال کردن اجزای برنامه"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"به برنامه اجازه می‎دهد تا فعال بودن یا نبودن اجزای برنامهٔ دیگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا قابلیتهای مهم رایانه لوحی را غیرفعال کنند. باید دقت کرد که با این مجوز ممکن است وضعیت اجزای برنامه ناپایدار، ناهماهنگ یا غیرقابل استفاده شود."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"به برنامه اجازه می‎دهد تا فعال بودن یا نبودن اجزای برنامهٔ دیگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا قابلیتهای مهم رایانهٔ لوحی را غیرفعال کنند. باید دقت کرد که با این مجوز ممکن است وضعیت اجزای برنامه ناپایدار، ناهماهنگ یا غیرقابل استفاده شود."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"به برنامه اجازه می‎دهد تا فعال بودن یا غیرفعال بودن جزئیات برنامهٔ دیگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا ویژگی‌های مهم را غیرفعال کنند. برای این مجوز باید دقت کنید چون ممکن است وضعیت جزئیات برنامه ناپایدار، بی‎ثبات یا غیرقابل استفاده شود."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"ارائه یا لغو مجوزها"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"به یک برنامه کاربردی اجازه می‌دهد تا مجوزهای خاصی را برای خود یا دیگر برنامه‌ها ارائه کرده یا آن‌ها را لغو کند. برنامه‌های مضر از این حالت برای دسترسی به ویژگی‌هایی استفاده می‌کنند که شما اجازه آن را در اختیارشان قرار نداده‌اید."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"به یک برنامهٔ کاربردی اجازه می‌دهد تا مجوزهای خاصی را برای خود یا دیگر برنامه‌ها ارائه کرده یا آن‌ها را لغو کند. برنامه‌های مضر از این حالت برای دسترسی به ویژگی‌هایی استفاده می‌کنند که شما اجازه آن را در اختیارشان قرار نداده‌اید."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"تنظیم برنامه‎های ترجیحی"</string>
-    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه می‎دهد تا برنامه‎های ترجیحی شما را تغییر دهد. برنامه‎های مخرب می‎توانند بدون اعلان برنامه‎هایی را که اجرا می‎شوند، تغییر دهند خود را به جای برنامه‎های کنونی قلمداد کنند تا داده‎های شخصی را از شما جمع آوری کنند."</string>
+    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه می‎دهد تا برنامه‎های ترجیحی شما را تغییر دهد. برنامه‎های مخرب می‎توانند بدون اعلان برنامه‎هایی را که اجرا می‎شوند، تغییر دهند خود را به جای برنامه‎های کنونی قلمداد کنند تا داده‎های شخصی را از شما جمع‌آوری کنند."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"اصلاح تنظیمات سیستم"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"به برنامه اجازه می‎دهد تا داده‎های تنظیم سیستم را تغییر دهد. برنامه‎های مخرب می‎توانند پیکربندی سیستم شما را خراب کنند."</string>
     <string name="permlab_writeSecureSettings" msgid="204676251876718288">"اصلاح کردن تنظیمات سیستم ایمن"</string>
@@ -339,36 +343,36 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"اصلاح کردن نقشه سرویس‌های Google"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"به برنامه اجازه می‎دهد تا نقشه سرویس‌های Google را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"اجرا شدن در هنگام راه‌اندازی"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"به برنامه اجازه می‎دهد تا به محض اتمام راه‎اندازی سیستم خودبخود شروع به کار کند. این کار ممکن است باعث شود مدت زمان بیشتری صرف شدوع به کار رایانه لوحی شود و به برنامه اجازه می‎دهد تا با اجرای همیشگی رایانه لوحی را کند کند."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"به برنامه اجازه می‎دهد تا به محض اتمام راه‎اندازی سیستم خودبخود شروع به کار کند. این کار ممکن است باعث شود مدت زمان بیشتری صرف شدوع به کار رایانهٔ لوحی شود و به برنامه اجازه می‎دهد تا با اجرای همیشگی رایانهٔ لوحی را کند کند."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"به برنامه اجازه می‎دهد تا به محض اینکه سیستم راه‎اندازی شد خودبخود شروع به کار کند. این کار باعث می‎شود مدت زمان بیشتری صرف شود تا تلفن شروع به کار کند و به برنامه اجازه می‎دهد تا کل تلفن کند شود چون همیشه در حال اجرا شدن است."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ارسال پخش چسبنده"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانه لوحی شود."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانهٔ لوحی شود."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری تلفن شود."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"خواندن مخاطبین شما"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این با برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این با برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری با افراد خاصی ارتباط برقرار کرده‌اید. این به برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"اصلاح مخاطبین شما"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"خواندن گزارش تماس"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"به برنامه اجازه می‌دهد گزارش تماس رایانه لوحی شما را بخواند از جمله داده‌های مربوط به تماس‌های ورودی و خروجی. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های گزارش تماس شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"به برنامه اجازه می‌دهد گزارش تماس رایانهٔ لوحی شما را بخواند از جمله داده‌های مربوط به تماس‌های ورودی و خروجی. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های گزارش تماس شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"به برنامه اجازه می‌دهد گزارش تماس تلفنی شما را بخواند از جمله داده‌های مربوط به تماس‌های ورودی و خروجی. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های گزارش تماس شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"نوشتن گزارش تماس"</string>
-    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه می‌دهد گزارشات تماس رایانه لوحی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
+    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه می‌دهد گزارشات تماس رایانهٔ لوحی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"به برنامه اجازه می‌دهد گزارشات تماس تلفنی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"خواندن کارت تماس شما"</string>
-    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه می‎دهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را به دیگران ارسال کند."</string>
+    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه می‎دهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را به دیگران ارسال کند."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"اصلاح کارت تماس شما"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را برای دیگران ارسال کند."</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را برای دیگران ارسال کند."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"خواندن جریان اجتماعی شما"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه می‌دهد به به‌روزرسانی‌های اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آن‌ها را همگام‌سازی کند. دقت کنید که هنگام اشتراک‌گذاری -- این ویژگی به برنامه اجازه می‌دهد ارتباطات بین شما و دوستان شما را در شبکه‌های اجتماعی، صرفنظر از محرمانه بودن آن‌ها بخواند. توجه: این مجوز ممکن است در همه شبکه‌های اجتماعی اجرا نشود."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"نوشتن در جریان اجتماعی شما"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"به برنامه اجازه می‌دهد به‌روزرسانی‌های اجتماعی از طرف دوستان شما را نمایش دهد. دقت کنید هنگام اشتراک‌گذاری اطلاعات -- این ویژگی به برنامه اجازه می‌دهد پیام‌هایی را که به نظر می‌رسد از طرف یکی از دوستان شما باشد ایجاد کند. توجه: این مجوز در همه شبکه‌های اجتماعی قابل اجرا نیست."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"خواندن رویدادهای تقویم به همراه اطلاعات محرمانه"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در رایانهٔ لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در تلفن شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"افزودن یا تغییر رویدادهای تقویم و ارسال ایمیل به مهمانان بدون دخالت مالک"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در رایانه لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در رایانهٔ لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در تلفن خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"منابع مکان کاذب برای تست"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
@@ -377,7 +381,7 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"مجوز برای نصب یک ارائه دهنده مکان"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
     <string name="permlab_accessFineLocation" msgid="5885550969882561436">"موقعیت مکانی دقیق (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در رایانه لوحی خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در رایانهٔ لوحی خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در تلفن خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
     <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"موقعیت مکانی تقریبی (مبتنی بر شبکه)"</string>
     <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"به موقعیت مکانی تقریبی ارا‌ئه‌دهندگان موقعیت مکانی با استفاده از منابع شبکه مانند برج مخابراتی و Wi-Fi دسترسی پیدا کنید. وقتی این سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه امکان می‌دهد موقعیت مکانی تقریبی شما را تعیین کند."</string>
@@ -391,14 +395,14 @@
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"به برنامه اجازه می‌دهد صدا را با میکروفن ضبط کند. این مجوز به برنامه اجازه می‌دهد صدا را در هر زمان که بخواهید بدون تأیید شما ضبط کند."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"عکسبرداری و فیلمبرداری"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"به برنامه اجازه می‌دهد با دوربین به عکسبرداری و فیلمبرداری بپردازد. این مجوز به برنامه اجازه می‌‌دهد از دوربین در هر زمانی بدون تأیید شما استفاده کند."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانه لوحی"</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانهٔ لوحی"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"تلفن بطور دائمی غیرفعال شود"</string>
-    <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"به برنامه اجازه می‎دهد تا رایانه لوحی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string>
+    <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"به برنامه اجازه می‎دهد تا رایانهٔ لوحی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string>
     <string name="permdesc_brick" product="default" msgid="5788903297627283099">"به برنامه اجازه می‎دهد تا گوشی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"راه اندازی مجدد اجباری رایانه لوحی"</string>
-    <string name="permlab_reboot" product="default" msgid="2898560872462638242">"اجبار برنامه برای راه اندازی مجدد"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"به برنامه اجازه می‎دهد تا سبب راه اندازی مجدد رایانه لوحی شود."</string>
-    <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"به برنامه اجازه می‎دهد تا سبب راه اندازی مجدد گوشی شود."</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"راه‌اندازی مجدد اجباری رایانهٔ لوحی"</string>
+    <string name="permlab_reboot" product="default" msgid="2898560872462638242">"اجبار برنامه برای راه‌اندازی مجدد"</string>
+    <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"به برنامه اجازه می‎دهد تا سبب راه‌اندازی مجدد رایانهٔ لوحی شود."</string>
+    <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"به برنامه اجازه می‎دهد تا سبب راه‌اندازی مجدد گوشی شود."</string>
     <string name="permlab_mount_unmount_filesystems" product="nosdcard" msgid="2927361537942591841">"دسترسی به سیستم فایل حافظهٔ USB"</string>
     <string name="permlab_mount_unmount_filesystems" product="default" msgid="4402305049890953810">"دسترسی به سیستم فایل کارت SD"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"به برنامه اجازه می‎دهد تا فایل‌های سیستمی در حافظه جداشدنی نصب شود یا نصب آن لغو شود."</string>
@@ -423,14 +427,14 @@
     <string name="permdesc_manageUsb" msgid="7776155430218239833">"به برنامه اجازه می‎دهد تا تنظیمات برگزیده و مجوزهای دستگاه‌های USB را مدیریت کند."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"اعمال پروتکل MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"دسترسی به درایور کرنل MTP جهت اعمال پروتکل MTP USB را اجازه می‌دهد."</string>
-    <string name="permlab_hardware_test" msgid="4148290860400659146">"تست سخت افزار"</string>
+    <string name="permlab_hardware_test" msgid="4148290860400659146">"تست سخت‌افزار"</string>
     <string name="permdesc_hardware_test" msgid="6597964191208016605">"به برنامه اجازه می‎دهد به منظور تست سخت‌افزار، قسمت‌های جانبی مختلف را کنترل کنند."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"تماس مستقیم با شماره تلفن‌ها"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"به برنامه اجازه می‌دهد بدون دخالت شما با شماره‌های تلفن تماس بگیرد. این ممکن است باعث ایجاد هزینه یا تماس‌های پیش‌بینی نشده شود. توجه داشته باشید که این به برنامه اجازه نمی‌دهد به برقراری تماس‌های اضطراری بپردازد. برنامه‌های مخرب ممکن است با برقراری تماس بدون تأیید شما هزینه‌هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"تماس مستقیم با هر شماره تلفنی"</string>
     <string name="permdesc_callPrivileged" msgid="1689024901509996810">"به برنامه اجازه می‎دهد تا بدون دخالت با هر شماره تلفنی تماس بگیرد، از جمله شماره‎های اضطراری. برنامه‎های مخرب می‎توانند تماس‌های غیرضروری و غیر قانونی با خدمات اضطراری بگیرند."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"راه اندازی مستقیم تنظیم رایانه لوحی CDMA"</string>
-    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"شروع مستقیم راه اندازی تلفن CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"راه‌اندازی مستقیم تنظیم رایانهٔ لوحی CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"شروع مستقیم راه‌اندازی تلفن CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"به برنامه اجازه می‎دهد تا شرایط مقررات CDMA را شروع کند. برنامه‎های مخرب می‎توانند شرایط مقررات CDMA را در مواقع غیرضروری شروع کند."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"کنترل اعلان‌های به‌روزرسانی مکان"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"به برنامه اجازه می‎دهد اعلانهای به‎روزرسانی موقعیت مکانی را از رادیو فعال/غیرفعال کند. برای استفاده برنامه‎های عادی نیست."</string>
@@ -442,17 +446,17 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"به برنامه اجازه می‎دهد ویژگی‌های دستگاه را کنترل کند. برنامه‎ای که این مجوز را دارد می‎تواند بدون اطلاع شما تعویض شبکه داشته باشد، رادیوی تلفن را روشن یا خاموش کند و کارهایی از این قبیل را انجام دهد."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه می‌دهد به ویژگی‌های تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه می‌دهد شماره تلفن و شناسه‌های دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانه لوحی"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانهٔ لوحی"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ممانعت از به خواب رفتن تلفن"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"به برنامه اجازه می‎دهد تا از غیرفعال شدن رایانه لوحی جلوگیری کند."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"به برنامه اجازه می‎دهد تا از غیرفعال شدن رایانهٔ لوحی جلوگیری کند."</string>
     <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"به برنامه اجازه می‎دهد تا از غیرفعال شدن تلفن جلوگیری کند."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"روشن/خاموش کردن رایانه لوحی"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"روشن/خاموش کردن رایانهٔ لوحی"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"روشن/خاموش کردن تلفن"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"به برنامه اجازه می‎دهد رایانه لوحی را روشن یا خاموش کند."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"به برنامه اجازه می‎دهد رایانهٔ لوحی را روشن یا خاموش کند."</string>
     <string name="permdesc_devicePower" product="default" msgid="6037057348463131032">"به برنامه اجازه می‎دهد گوشی را روشن یا خاموش کند."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"اجرا در حالت تست کارخانه"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سخت افزار رایانه لوحی شما را فراهم می‌آورد. فقط زمانی که رایانه لوحی در حالت تست سازنده در حال اجراست قابل دسترسی است."</string>
-    <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سخت افزار تلفن شما را فراهم می‌آورد. فقط زمانی که تلفن در حالت تست سازنده در حال اجراست قابل دسترسی است."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سخت‌افزار رایانهٔ لوحی شما را فراهم می‌آورد. فقط زمانی که رایانهٔ لوحی در حالت تست سازنده در حال اجراست قابل دسترسی است."</string>
+    <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سخت‌افزار تلفن شما را فراهم می‌آورد. فقط زمانی که تلفن در حالت تست سازنده در حال اجراست قابل دسترسی است."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"تنظیم تصویر زمینه"</string>
     <string name="permdesc_setWallpaper" msgid="7373447920977624745">"به برنامه اجازه می‎دهد تا تصویر زمینه سیستم را تنظیم کند."</string>
     <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"تنظیم اندازه تصویر زمینه"</string>
@@ -460,15 +464,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"بازنشانی سیستم به موارد پیش‌فرض کارخانه"</string>
     <string name="permdesc_masterClear" msgid="3665380492633910226">"به برنامه اجازه می‎دهد تا بطور کامل سیستم را روی تنظیمات کارخانه بازنشانی کند، همه داده‎ها، پیکربندی و برنامه‎های نصب شده را پاک کند."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"تنظیم ساعت"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"به برنامه اجازه می‎دهد تا زمان ساعت رایانه لوحی را تغییر دهد."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"به برنامه اجازه می‎دهد تا زمان ساعت رایانهٔ لوحی را تغییر دهد."</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"به برنامه اجازه می‎دهد تا زمان ساعت تلفن را تغییر دهد."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"تنظیم منطقهٔ زمانی"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"به برنامه اجازه می‎دهد تا منطقهٔ زمانی رایانه لوحی را تغییر دهد."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"به برنامه اجازه می‎دهد تا منطقهٔ زمانی رایانهٔ لوحی را تغییر دهد."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"به برنامه اجازه می‎دهد تا منطقهٔ زمانی تلفن را تغییر دهد."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"عملکرد به عنوان AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"به برنامه اجازه می‎دهد با AccountAuthenticators تماس برقرار کند."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"یافتن حساب‌ها در دستگاه"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط رایانه لوحی دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط رایانهٔ لوحی دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط تلفن دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"ایجاد حساب‌ها و تنظیم گذرواژ‌ه‌ها"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"به برنامه اجازه می‎دهد از امکانات تأیید کننده اعتبار حساب AccountManager از جمله ایجاد حساب و دریافت و تنظیم گذرواژه‎ها استفاده کند."</string>
@@ -493,18 +497,18 @@
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"اتصال به Wi-Fi و قطع اتصال از آن"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"به برنامه اجازه می‎دهد تا به نقاط دسترسی Wi-Fi وصل شود و ارتباط خود را با آن‌ها قطع کند و تغییراتی را در پیکربندی دستگاه برای شبکه‎های Wi-Fi ایجاد کند."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"دریافت چندگانه Wi-Fi را مجاز می‌کند"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به رایانه لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به رایانهٔ لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه می‎دهد تا رایانه لوحی بلوتوث محلی را پیکربندی کرده، دستگاه‌های راه دور را شناسایی کرده و با آن‌ها جفت شود."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه می‎دهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاه‌های راه دور را شناسایی کرده و با آن‌ها جفت شود."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه می‎دهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاه‌های راه دور را پیدا کند و با آن‌ها جفت شود."</string>
     <string name="permlab_accessWimaxState" msgid="7436749103151096452">"مشاهدهٔ اتصالات وایمکس"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"به برنامه امکان می‌دهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکه‌های وایمکس متصل را مشخص کند."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغییر وضعیت WiMAX"</string>
-    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان می‌دهد رایانه لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند."</string>
+    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان می‌دهد رایانهٔ لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"به برنامه امکان می‎دهد تا تلفن را به شبکه‌های وایمکس متصل کرده یا اتصال آنرا از این شبکه‌ها قطع کند."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"مرتبط‌ سازی با دستگاه‌های بلوتوث"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در رایانه لوحی را مشاهده کند و اتصال با دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"کنترل ارتباط راه نزدیک"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"به برنامه اجازه می‎دهد تا با تگهای ارتباط میدان نزدیک (NFC)، کارتها و فایل خوان ارتباط برقرار کند."</string>
@@ -534,8 +538,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"به برنامه اجازه می‎دهد تا در کارت SD بنویسد."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"تغییر/حذف محتواهای حافظه رسانه داخلی"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"به برنامه اجازه می‎دهد تا محتویات حافظه رسانه داخلی را تغییر دهد."</string>
-    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظه پنهان"</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه می‎دهد تا سیستم فایل حافظه پنهان را بخواند و بنویسد."</string>
+    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظهٔ پنهان"</string>
+    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه می‎دهد تا سیستم فایل حافظهٔ پنهان را بخواند و بنویسد."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"علامتگذاری/دریافت تماس‌های اینترنتی"</string>
     <string name="permdesc_use_sip" msgid="4717632000062674294">"به برنامه اجازه می‎دهد تا از خدمات SIP استفاده کند و تماس‌های اینترنتی بگیرد/دریافت کند."</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"خواندن سابقه استفاده از شبکه"</string>
@@ -547,19 +551,19 @@
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسه‎های مجاز در گذرواژه‌های بازکردن قفل صفحه را کنترل کنید."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژه‎های اشتباه تایپ شده را هنگام بازکردن قفل صفحه کنترل می‌کند، و یا اگر دفعات زیادی گذرواژه اشتباه تایپ شود رایانه لوحی را قفل می‎کند و همه داده‎های رایانه لوحی را پاک می‎کند."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژه‎های اشتباه تایپ شده را هنگام بازکردن قفل صفحه کنترل می‌کند، و یا اگر دفعات زیادی گذرواژه اشتباه تایپ شود رایانهٔ لوحی را قفل می‎کند و همه داده‎های رایانهٔ لوحی را پاک می‎کند."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"تعداد گذرواژه‎های نادرست تایپ شده را کنترل می‎کند. هنگام بازکردن قفل صفحه اگر دفعات زیادی گذرواژه نادرست تایپ کرده‎اید، تلفن را قفل کنید یا همه داده‎های تلفن را پاک کنید."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"تغییر رمز ورود قفل گشایی صفحه"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"گذرواژه بازگشایی قفل صفحه را تغییر دهید."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"قفل کردن صفحه"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"نحوه و زمان قفل شدن صفحه را کنترل کنید."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"پاک کردن تمام داده‌ها"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به داده‌های کارخانه، داده‌های رایانه لوحی بدون هشدار پاک می‌شود."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به داده‌های کارخانه، داده‌های رایانهٔ لوحی بدون هشدار پاک می‌شود."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"با انجام بازنشانی به داده‌های کارخانه، داده‌های تلفن بدون هشدار پاک می‌شود."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تنظیم پروکسی جهانی دستگاه"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"پروکسی جهانی دستگاه مورد نظر را جهت استفاده هنگام فعال بودن خط مشی تنظیم کنید. فقط اولین سرپرست دستگاه پروکسی جهانی مفید را تنظیم می‌کند."</string>
     <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود قفل صفحه"</string>
-    <string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یکبار باید گذرواژه صفحه قفل عوض شود."</string>
+    <string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یک بار باید گذرواژه صفحه قفل عوض شود."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"باید اطلاعات ذخیره شده برنامه رمزگذاری شود."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"غیر فعال کردن دوربین ها"</string>
@@ -703,7 +707,7 @@
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"شارژر خود را متصل کنید."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"سیم کارت موجود نیست."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانه لوحی نیست."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانهٔ لوحی نیست."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"سیم کارت درون تلفن نیست."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"سیم کارت را وارد کنید."</string>
     <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"سیم کارت موجود نیست یا قابل خواندن نیست. یک سیم کارت وارد کنید."</string>
@@ -721,13 +725,13 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"سیم کارت قفل شد."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"بازگشایی قفل سیم کارت..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژه خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کرده‌اید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژهٔ خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کرده‌اید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"پین را<xliff:g id="NUMBER_0">%d</xliff:g>  بار اشتباه تایپ کرده‎اید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که برای بازگشایی قفل رایانه لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر از شما خواسته می‎شود که برای بازگشایی قفل گوشی خود به برنامه Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانه لوحی کرده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانه لوحی به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که برای بازگشایی قفل رایانهٔ لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر از شما خواسته می‎شود که برای بازگشایی قفل گوشی خود به برنامهٔ Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانهٔ لوحی کرده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانهٔ لوحی به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. پس از<xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، تلفن به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
-    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانه لوحی کرده‌اید. رایانه لوحی در حال حاضر به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
+    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانهٔ لوحی کرده‌اید. رایانهٔ لوحی در حال حاضر به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. این تلفن در حال حاضر به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"در <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"الگو را فراموش کرده‌اید؟"</string>
@@ -738,7 +742,7 @@
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"رمز ورود"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ورود به سیستم"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"نام کاربر یا رمز ورود نامعتبر است."</string>
-    <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژه خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string>
+    <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژهٔ خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string>
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"در حال بررسی..."</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"بازگشایی قفل"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"صدا روشن"</string>
@@ -758,8 +762,8 @@
     <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"تست کارخانه انجام نشد"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"عملکرد FACTORY_TEST تنها برای بسته‌های نصب شده در /system/app پشتیبانی می‌شود."</string>
-    <string name="factorytest_no_action" msgid="872991874799998561">"بسته ای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"راه اندازی مجدد"</string>
+    <string name="factorytest_no_action" msgid="872991874799998561">"بسته‌ای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"راه‌اندازی مجدد"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"صفحه در \"<xliff:g id="TITLE">%s</xliff:g>\" می‎گوید:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"جاوا اسکریپت"</string>
     <string name="js_dialog_before_unload" msgid="730366588032430474">"از این صفحه خارج می‎شوید؟"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"برای ادامه روی تأیید و برای ماندن در همین صفحه روی لغو کلیک کنید."</string>
@@ -786,7 +790,7 @@
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"خواندن سابقه و نشانک‌های وب شما"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"به برنامه اجازه می‌دهد سابقه نشانی‌های اینترنتی را که مرورگر بازدید کرده است و همه نشانک‌های مرورگر را بخواند. توجه: این مجوز توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نیست."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"نوشتن نشانک‌های وب و سابقه"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در رایانه لوحی شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در رایانهٔ لوحی شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در تلفن شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"تنظیم یک هشدار"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"به برنامه اجازه می‎دهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامه‎های ساعت زنگدار نمی‎توانند این ویژگی را اعمال کنند."</string>
@@ -822,7 +826,7 @@
     <string name="searchview_description_submit" msgid="2688450133297983542">"ارسال عبارت جستجو"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"جستجوی صوتی"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"فعال کردن «کاوش با لمس»؟"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> می‌خواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، می‌توانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانه لوحی از حرکات اشاره استفاده کنید."</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> می‌خواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، می‌توانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانهٔ لوحی از حرکات اشاره استفاده کنید."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> می‌خواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، می‌توانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از تلفن خود از حرکات اشاره استفاده کنید."</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"۱ ماه قبل"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"قبل از ۱ ماه گذشته"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"کپی URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"انتخاب متن"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"انتخاب متن"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"افزودن به فرهنگ لغت"</string>
-    <string name="deleteText" msgid="7070985395199629156">"حذف"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"افزودن به فرهنگ‌لغت"</string>
+    <string name="deleteText" msgid="6979668428458199034">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"روش ورودی"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"عملکردهای متنی"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"فضای ذخیره‌سازی رو به اتمام است"</string>
@@ -964,7 +968,7 @@
     <string name="webpage_unresponsive" msgid="3272758351138122503">"این صفحه پاسخ نمی‌دهد."\n\n"آیا می‌خواهید آن را ببندید؟"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"برنامه مجدداً هدایت شد"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> اکنون در حال اجرا است."</string>
-    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ابتدا راه اندازی شد."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ابتدا راه‌اندازی شد."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"مقیاس"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"همیشه نشان داده شود"</string>
     <string name="screen_compat_mode_hint" msgid="1064524084543304459">"در تنظیمات سیستم &gt;برنامه‎ها &gt; مورد دانلود شده آن را دوباره فعال کنید."</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; در حال ارسال تعداد زیادی پیامک است. آیا اجازه می‌دهید این برنامه همچنان پیامک ارسال کند؟"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"اجازه دادن"</string>
     <string name="sms_control_no" msgid="625438561395534982">"ردکردن"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"پیامک به کد کوتاه ارسال شود؟"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"پیامک ممتاز ارسال شود؟"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; می‌خواهد یک پیام نوشتاری را به &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ارسال کند که به نظر می‌رسد یک کد کوتاه پیامک است.&lt;p&gt;ارسال پیام‌های نوشتاری به برخی از کدهای کوتاه ممکن است باعث شود برای حساب تلفن همراه شما بابت استفاده از سرویس‌های ممتاز صورتحساب ارسال شود.&lt;p&gt;آیا به این برنامه اجازه می‌دهید پیام ارسال کند؟"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; می‌خواهد یک پیام نوشتاری را به &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ارسال کند که یک کد کوتاه پیامک ممتاز است.&lt;p&gt;&lt;b&gt;ارسال پیام به این مقصد ممکن است باعث شود برای حساب تلفن همراه شما بابت استفاده از سرویس‌های ممتاز صورتحساب ارسال شود.&lt;/b&gt;&lt;p&gt;آیا به این برنامه اجازه می‌دهید پیامک ارسال کند؟"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"ارسال پیام"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"ارسال نشود"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"گزارش برنامه مخرب"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"سیم کارت برداشته شد"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"تا وقتی که با یک سیم‌کارت معتبر راه‌اندازی مجدد نکنید شبکه تلفن همراه غیر قابل‌ دسترس خواهد بود."</string>
     <string name="sim_done_button" msgid="827949989369963775">"انجام شد"</string>
@@ -1051,17 +1062,17 @@
     <string name="perms_description_app" msgid="5139836143293299417">"ارائه شده توسط <xliff:g id="APP_NAME">%1$s</xliff:g> ."</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"حافظه انبوه USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل شد"</string>
-    <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"شما از طریق USB به رایانه خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانه خود و حافظهٔ USB در Android کپی کنید، دکمه زیر را لمس کنید."</string>
-    <string name="usb_storage_message" product="default" msgid="805351000446037811">"شما از طریق USB به رایانه خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانه خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"شما از طریق USB به رایانهٔ خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانهٔ خود و حافظهٔ USB در Android کپی کنید، دکمه زیر را لمس کنید."</string>
+    <string name="usb_storage_message" product="default" msgid="805351000446037811">"شما از طریق USB به رایانهٔ خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانهٔ خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"روشن کردن دستگاه ذخیره‌سازی USB"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"هنگام استفاده از حافظهٔ USB برای حافظه انبوه USB مشکلی بوجود آمد."</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"هنگام استفاده از کارت SD برای حافظه ذخیره انبوه USB مشکلی بوجود آمد."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB متصل شد"</string>
-    <string name="usb_storage_notification_message" msgid="939822783828183763">"برای کپی کردن فایل‌ها از/به رایانه خود لمس کنید."</string>
+    <string name="usb_storage_notification_message" msgid="939822783828183763">"برای کپی کردن فایل‌ها از/به رایانهٔ خود لمس کنید."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"خاموش کردن دستگاه ذخیره‌سازی USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"برای غیرفعال کردن حافظهٔ USB، لمس کنید."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"دستگاه ذخیره‌سازی USB در حال استفاده است"</string>
-    <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"قبل از غیرفعال کردن حافظهٔ USB، حافظهٔ USB مربوط به Android را در رایانه خود لغو نصب کنید (\"خارج کنید\")."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"قبل از غیرفعال کردن حافظهٔ USB، حافظهٔ USB مربوط به Android را در رایانهٔ خود لغو نصب کنید (\"خارج کنید\")."</string>
     <string name="usb_storage_stop_message" product="default" msgid="8043969782460613114">"قبل از غیرفعال کردن حافظهٔ USB، کارت SD مربوط به Android را در رایانه لغو نصب کنید (\"خارج کنید\")."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"خاموش کردن دستگاه ذخیره‌سازی USB"</string>
     <string name="usb_storage_stop_error_message" msgid="1970374898263063836">"هنگام غیرفعال کردن حافظهٔ USB مشکلی بوجود آمد. بررسی کنید میزبان USB را لغو نصب کرده باشید، سپس دوباره امتحان کنید."</string>
@@ -1069,7 +1080,7 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"در صورت فعال کردن حافظهٔ USB، برخی از برنامه‎هایی که از آن‌ها استفاده می‎کنید متوقف می‎شوند و تا زمانی که حافظهٔ USB را غیرفعال نکنید امکان استفاده از آن‌ها وجود نخواهد داشت."</string>
     <string name="dlg_error_title" msgid="7323658469626514207">"راه‌اندازی USB ناموفق بود."</string>
     <string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string>
-    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به عنوان دستگاه رسانه ای"</string>
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به عنوان دستگاه رسانه‌ای"</string>
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده به عنوان دوربین"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده به عنوان نصب کننده"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"به یک وسیله جانبی USB وصل شده است"</string>
@@ -1083,10 +1094,10 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"برای غیرفعال کردن اشکال زدایی USB لمس کنید."</string>
     <string name="select_input_method" msgid="4653387336791222978">"انتخاب روش ورودی"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"تنظیم روش‌های ورودی"</string>
-    <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه کلید فیزیکی"</string>
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه‌کلید فیزیکی"</string>
     <string name="hardware" msgid="7517821086888990278">"سخت‌افزار"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرح‌بندی صفحه کلید"</string>
-    <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرح‌بندی صفحه کلید لمس کنید…"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرح‌بندی صفحه‌کلید"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرح‌بندی صفحه‌کلید لمس کنید…"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string>
@@ -1101,8 +1112,8 @@
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"کارت SD آسیب دیده"</string>
     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="1795917578395333280">"حافظهٔ USB خراب است. سعی کنید آنرا دوباره فرمت کنید."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="1753898567525568253">"کارت SD خراب است. سعی کنید آنرا دوباره فرمت کنید."</string>
-    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظهٔ USB به صورت غیر منتظره جدا شد"</string>
-    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیر منتظره ای جدا شد"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظهٔ USB به صورت غیرمنتظره جدا شد"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیرمنتظره‌ای جدا شد"</string>
     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"اتصال حافظهٔ USB را قبل از بیرون آوردن قطع کنید تا سبب از بین رفتن داده‌ها نشود."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"کارت SD را قبل از بیرون آوردن جدا کنید تا سبب از بین رفتن داده‌ها نشود."</string>
     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"حافظهٔ USB را می‌توانید با ایمنی جدا کنید"</string>
@@ -1272,7 +1283,7 @@
     <string name="fingerprints" msgid="4516019619850763049">"اثر انگشت:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"اثر انگشت SHA-256:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"اثر انگشت SHA-1"</string>
-    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"مشاهده همه"</string>
+    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"مشاهدهٔ همه"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"انتخاب فعالیت"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"اشتراک‌گذاری با"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"دستگاه قفل است."</string>
@@ -1282,7 +1293,7 @@
     <string name="SetupCallDefault" msgid="5834948469253758575">"تماس را می‌پذیرید؟"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"همیشه"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"فقط این بار"</string>
-    <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانه لوحی"</string>
+    <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانهٔ لوحی"</string>
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"تلفن"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"هدفون‌ها"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"بلندگوهای جایگاه اتصال"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index bd28a20..edf133a 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Antaa sovelluksen noutaa järjestelmän sisäisen tilan. Haitalliset sovellukset voivat noutaa paljon yksityisiä ja suojattuja tietoja, joita niiden ei pitäisi tarvita normaalisti."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"nouda näytön sisältö"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Antaa sovelluksen noutaa aktiivisen ikkunan sisällön. Haitalliset sovellukset voivat noutaa koko ikkunan sisällön ja tarkastella sen kaikkea tekstiä lukuun ottamatta salasanoja."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"nouda ikkunoiden tietoja"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Antaa sovelluksen noutaa ikkunoiden tietoja ikkunanhallinnasta. Haitalliset sovellukset voivat noutaa tietoja, jotka on tarkoitettu järjestelmän sisäiseen käyttöön."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"suodata tapahtumat"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Antaa sovelluksen rekisteröidä syöttösuodattimen, joka suodattaa kaikkien käyttäjätapahtumien streamin ennen tapahtumien näyttämistä. Haitalliset sovellukset voivat hallita järjestelmän käyttöliittymää ilman käyttäjän lupaa."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"sulje puhelin osittain"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Asettaa toimintojen hallinnan sulkeutumistilaan. Ei sulje puhelinta kokonaan."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopioi URL-osoite"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Valitse tekstiä"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstin valinta"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"lisää sanakirjaan"</string>
-    <string name="deleteText" msgid="7070985395199629156">"poista"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Lisää sanakirjaan"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Poista"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Syöttötapa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoiminnot"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Tallennustila loppumassa"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lähettää suuria määriä tekstiviestejä. Annetaanko tämän sovelluksen jatkaa tekstiviestien lähettämistä?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Salli"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Kiellä"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Lähetetäänkö viesti?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Lähetä maksullinen viesti?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haluaa lähettää tekstiviestin kohteeseen &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, joka voi olla maksullinen numero.&lt;p&gt;&lt;b&gt;Jos lähetät viestin tähän kohteeseen, sinua saatetaan veloittaa maksullisten palveluiden käytöstä.&lt;/b&gt;&lt;p&gt;Annetaanko sovelluksen lähettää viesti?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haluaa lähettää tekstiviestin kohteeseen &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, joka on maksullinen numero.&lt;p&gt;&lt;b&gt;Jos lähetät viestin tähän kohteeseen, sinua veloitetaan maksullisten palveluiden käytöstä.&lt;/b&gt;&lt;p&gt;Annetaanko sovelluksen lähettää viesti?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Lähetä viesti"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Älä lähetä"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Ilmoita haittasovelluksesta"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortti poistettu"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobiiliverkko ei ole käytettävissä, ennen kuin käynnistät uudelleen kelvollisella laitteeseen kytketyllä SIM-kortilla."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e000f93..58ae361 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permet à l\'application de récupérer l\'état interne du système. Des applications malveillantes peuvent récupérer de nombreuses informations confidentielles et sécurisées dont elles ne devraient pas avoir besoin normalement."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"récupérer le contenu de l\'écran"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet à l\'application de récupérer le contenu de la fenêtre active. Des applications malveillantes peuvent exploiter cette fonctionnalité pour récupérer et lire la totalité du contenu de la fenêtre, à l\'exception des mots de passe."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"récupérer les informations sur les fenêtres"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet à une application de récupérer les informations sur les fenêtres depuis le gestionnaire de fenêtres. Des applications malveillantes peuvent récupérer des informations destinées à un usage interne du système."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer les événements"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet à une application d\'enregistrer un filtre d\'entrée pour filtrer le flux de tous les événements des utilisateurs avant qu\'ils ne soient traités. Des applications malveillantes peuvent contrôler l\'interface utilisateur du système sans l\'intervention de l\'utilisateur."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Place le gestionnaire d\'activités en état d\'arrêt. N\'effectue pas un arrêt complet."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copier l\'URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Sélectionner texte"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Sélection de texte"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"ajouter au dictionnaire"</string>
-    <string name="deleteText" msgid="7070985395199629156">"supprimer"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Ajouter au dictionnaire"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Supprimer"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mode de saisie"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Actions sur le texte"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Espace de stockage bientôt saturé"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envoie un grand nombre de SMS. Autorisez-vous cette application à poursuivre l\'envoi des messages ?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Autoriser"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Refuser"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Envoyer SMS au numéro abrégé ?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Envoyer un SMS premium ?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; essaie d\'envoyer un SMS à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Il s\'agit apparemment d\'un numéro abrégé.&lt;p&gt;L\'envoi de SMS à de tels numéros peut entraîner la facturation de services premium sur votre compte mobile.&lt;p&gt;Autorisez-vous cette application à envoyer ce message ?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; essaie d\'envoyer un SMS à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Il s\'agit apparemment d\'un numéro abrégé de type premium.&lt;p&gt;&lt;b&gt;L\'envoi de SMS à ce destinataire entraînera la facturation de services premium sur votre compte mobile.&lt;/b&gt;&lt;p&gt;Autorisez-vous cette application à envoyer le message ?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Envoyer le message"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ne pas envoyer"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Signaler appli malveillante"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Carte SIM retirée"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Le réseau mobile ne sera pas disponible avant le redémarrage avec une carte SIM valide insérée."</string>
     <string name="sim_done_button" msgid="827949989369963775">"OK"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6a43298..2e1c46a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"एप्‍लिकेशन को सिस्‍टम की आंतरिक स्‍थिति पुनर्प्राप्त करने देता है. दुर्भावनापूर्ण एप्‍लिकेशन विभिन्‍न प्रकार की निजी और सुरक्षा जानकारी प्राप्त कर सकते हैं जिनकी उन्‍हें सामान्‍यत: आवश्‍यकता नहीं होती."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"स्‍क्रीन सामग्री पुनर्प्राप्त करें"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"एप्‍लिकेशन को सक्रिय विंडो की सामग्री पुनर्प्राप्त करने देता है. दुर्भावनापूर्ण एप्‍लिकेशन विंडो की संपूर्ण सामग्री प्राप्त कर सकते हैं और पासवर्ड को छोड़कर इसके सभी पाठ जांच सकते हैं."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"विंडो जानकारी प्राप्त करें"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"एप्‍लिकेशन को विंडो प्रबंधक से windows के बारे में जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण एप्‍लिकेशन आंतरिक सिस्टम उपयोग के लिए अभिप्रेत जानकारी को प्राप्त कर सकते हैं."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"ईवेंट फ़िल्टर करें"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"एप्‍लिकेशन को इनपुट फ़िल्‍टर पंजीकृत करने देता है, जो सभी उपयोगकर्ता ईवेंट के स्‍ट्रीम को भेजे जाने से पहले फ़िल्‍टर करता है. दुर्भावनापूर्ण एप्‍लिकेशन उपयोगकर्ता के हस्‍तक्षेप के बिना सिस्‍टम UI को नियंत्रित कर सकता है."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"आंशिक शटडाउन"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"गतिविधि प्रबंधक को शटडाउन स्‍थिति में रखता है. पूर्ण शटडाउन निष्‍पादित नहीं करता है."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"एप्‍लिकेशन स्‍विच करने से रोकता है"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL की प्रतिलिपि बनाएं"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"पाठ का चयन करें"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"पाठ चयन"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"डिक्‍शनरी में जोड़ें"</string>
-    <string name="deleteText" msgid="7070985395199629156">"हटाएं"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"शब्दकोश में जोड़ें"</string>
+    <string name="deleteText" msgid="6979668428458199034">"हटाएं"</string>
     <string name="inputMethod" msgid="1653630062304567879">"इनपुट विधि"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"पाठ क्रियाएं"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"संग्रहण स्‍थान समाप्‍त हो रहा है"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; बड़ी संख्या में SMS संदेश भेज रहा है. क्या आप इस एप्लिकेशन को संदेश भेजना जारी रखने देना चाहते हैं?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"अनुमति दें"</string>
     <string name="sms_control_no" msgid="625438561395534982">"अस्वीकार करें"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"शॉर्ट कोड पर SMS भेजें?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"प्रीमियम SMS भेजें?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; को एक पाठ संदेश भेजना चाहता है, जो एक SMS शॉर्ट कोड लगता है.&lt;p&gt;कुछ शॉर्ट कोड को पाठ संदेश भेजने से आपके मोबाइल खाते पर प्रीमियम सेवाओं का शुल्क लिया जा सकता है.&lt;p&gt;क्या आप इस एप्लिकेशन को यह संदेश भेजने देना चाहते हैं?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; को एक पाठ संदेश भेजना चाहता है, जो एक प्रीमियम SMS शॉर्ट कोड है.&lt;p&gt;&lt;b&gt;इस गंतव्य पर कोई संदेश भेजने से आपके मोबाइल खाते पर प्रीमियम सेवाओं का शुल्क लिया जाएगा.&lt;/b&gt;&lt;p&gt;क्या आप इस एप्लिकेशन को संदेश भेजने देना चाहते हैं?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"संदेश भेजें"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"न भेजें"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"दुर्भावनापूर्ण एप्लि. की रिपोर्ट करें"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"सिमकार्ड निकाला गया"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"मान्‍य सि‍म कार्ड डालकर पुन: प्रारंभ करने तक मोबाइल नेटवर्क अनुपलब्‍ध रहेगा."</string>
     <string name="sim_done_button" msgid="827949989369963775">"पूर्ण"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a33e03e..41f34f6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Omogućuje aplikaciji dohvaćanje unutarnjeg stanja sustava. Zlonamjerne aplikacije mogu dohvatiti razne privatne i sigurnosne podatke koje im inače nikada ne bi trebale biti potrebne."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"dohvaćanje sadržaja zaslona"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Omogućuje aplikaciji dohvaćanje sadržaja aktivnog prozora. Zlonamjerne aplikacije mogu dohvatiti sav sadržaj prozora i pregledati sav njegov tekst osim zaporki."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"dohvaćanje informacija o prozoru"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Aplikaciji omogućuje dohvaćanje informacija o prozorima iz upravitelja prozora. Zlonamjerne aplikacije mogu dohvaćati informacije koje su namijenjene za internu uporabu sustava."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje događaja"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Aplikaciji omogućuje registraciju ulaznog filtra koji filtrira strujanje svih korisničkih događaja prije otpreme. Zlonamjerne aplikacije mogu kontrolirati korisničko sučelje sustava bez znanja korisnika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"djelomično isključivanje"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Postavlja upravitelja za aktivnost u stanje mirovanja. Ne isključuje ga u potpunosti."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"sprečavanje promjene aplikacije"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiraj URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Odabir teksta"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Odabir teksta"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"dodaj u rječnik"</string>
-    <string name="deleteText" msgid="7070985395199629156">"izbriši"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Dodaj u rječnik"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način unosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje s tekstom"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ponestaje prostora za pohranu"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; šalje veliki broj SMS poruka. Želite li dopustiti ovoj aplikaciji da nastavi slati poruke?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Dopusti"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odbij"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Poslati SMS na skraćeni broj?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Poslati premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati tekstnu poruku na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, a čini se da je to skraćeni SMS broj.&lt;p&gt;Slanje tekstnih poruka na neke skraćene interne brojeve može dovesti do naplate premium usluga na vašem računu mobilnog uređaja.&lt;p&gt;Želite li dopustiti aplikaciji da pošalje poruku?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati tekstnu poruku na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, a to je skraćeni premium SMS broj.&lt;p&gt;&lt;b&gt;Slanje poruke na taj broj dovest će do naplate premium usluga na vašem računu mobilnog uređaja.&lt;/b&gt;&lt;p&gt;Želite li dopustiti toj aplikaciji da pošalje poruku?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Pošalji poruku"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ne šalji"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Prijavi zlonamjerne aplikacije"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kartica uklonjena"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilna mreža bit će nedostupna do ponovnog pokretanja s umetnutom važećom SIM karticom."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gotovo"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9b878c2..f4526fa 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Lehetővé teszi az alkalmazás számára, hogy lekérje a rendszer belső állapotát. A rosszindulatú programok lekérhetnek számos olyan privát és biztonságos adatot, amelyekre normál esetben soha nincs szükségük."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"a képernyő tartalmának lekérése"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lehetővé teszi az alkalmazás számára az aktív ablak tartalmának letöltését. A rosszindulatú alkalmazások letölthetik az ablak teljes tartalmát, és a jelszavak kivételével az összes szöveget megvizsgálhatják."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ablakkal kapcsolatos információk lekérése"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lehetővé teszi, hogy az alkalmazás információkat kérjen le az ablakkezelőben lévő ablakokkal kapcsolatban. A rosszindulatú alkalmazások belső rendszerhasználathoz szükséges információkat kérhetnek le."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"események szűrése"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Lehetővé teszi az alkalmazás számára, hogy egy bemeneti szűrőt használjon, amely megszűri a falon megjelenő felhasználói eseményeket, még mielőtt megjelennének. A rosszindulatú alkalmazások felhasználói beavatkozás nélkül irányíthatják a rendszer kezelőfelületét."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"részleges rendszerleállítás"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Leállítás állapotba helyezi a tevékenységkezelőt. Nem hajtja végre a teljes leállítást."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL másolása"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Szöveg kijelölése"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Szöveg kijelölése"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"hozzáadás a szótárhoz"</string>
-    <string name="deleteText" msgid="7070985395199629156">"törlés"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Hozzáadás a szótárhoz"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Törlés"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Beviteli mód"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Műveletek szöveggel"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Kevés a szabad terület"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/ b&gt; nagyszámú SMS üzenetet küld. Engedélyezi, hogy ez az alkalmazás továbbra is üzeneteket küldjön?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Engedélyezés"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Elutasítás"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"SMS küldése a rövid kódra?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Elküldi az emelt díjas SMS-t?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy SMS rövid kódja.&lt;p&gt;Az egyes rövid kódokra küldött üzenetek miatt mobilszámláján emelt díjas szolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy emelt díjas SMS rövid kódja.&lt;p&gt;Az ide küldött üzenet miatt mobilszámláján emelt díjas szolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Üzenet küldése"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nincs küldés"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rosszindulatú alk. bejelentése"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kártya eltávolítva"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A mobilhálózat nem lesz elérhető, amíg újra nem indítja egy érvényes SIM kártya behelyezése után."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kész"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index a760e41..be91c49 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Mengizinkan apl mengambil keadaan internal sistem. Apl berbahaya dapat mengambil berbagai informasi pribadi dan aman yang seharusnya tidak diperlukan."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ambil konten layar"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Mengizinkan apl mengambil konten jendela aktif. Apl berbahaya dapat mengambil seluruh konten jendela dan memeriksa semua teksnya kecuali sandi."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"mengambil info jendela"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Mengizinkan aplikasi mengambil informasi tentang jendela dari pengelola jendela. Aplikasi berbahaya dapat mengambil informasi yang ditujukan untuk penggunaan sistem internal."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"memfilter acara"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Mengizinkan aplikasi mendaftarkan filter masukan yang memfilter streaming semua acara pengguna sebelum acara dikirimkan. Aplikasi berbahaya dapat mengontrol UI sistem tanpa campur tangan pengguna."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penghentian sebagian"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Letakkan pengelola aktivitas dalam kondisi mati. Tidak melakukan penonaktifan penuh."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Salin URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pilih teks"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pemilihan teks"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"tambahkan ke kamus"</string>
-    <string name="deleteText" msgid="7070985395199629156">"hapus"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Tambahkan ke kamus"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Hapus"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metode masukan"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ruang penyimpanan hampir habis"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sedang mengirim pesan SMS dalam jumlah besar. Izinkan aplikasi ini untuk melanjutkan pengiriman pesan?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Izinkan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Tolak"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Kirim SMS ke kode singkat?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Kirim SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; akan mengirim pesan teks ke &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang akan muncul sebagai kode singkat SMS.&lt;p&gt;Mengirim pesan teks ke beberapa kode singkat menyebabkan Anda dikenakan biaya layanan premium pada akun seluler Anda.&lt;p&gt;Izinkan aplikasi ini mengirim pesan?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; akan mengirim pesan teks ke &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang merupakan kode singkat SMS premium.&lt;p&gt;&lt;b&gt;Mengirim pesan ke tujuan ini menyebabkan Anda dikenakan biaya layanan premium pada akun seluler Anda.&lt;/b&gt;&lt;p&gt;Izinkan aplikasi ini mengirim pesan?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Kirim pesan"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Jangan kirim"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Laporkan aplikasi berbahaya"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kartu SIM dihapus"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Jaringan seluler tidak akan tersedia sampai Anda memulai lagi dengan memasukkan kartu SIM yang valid."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d912688..c492e2d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Consente all\'applicazione di recuperare lo stato interno del sistema. Le applicazioni dannose potrebbero recuperare una vasta gamma di informazioni private e protette di cui normalmente non dovrebbero mai avere bisogno."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recupero dei contenuti della schermata"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Consente all\'applicazione di recuperare i contenuti della finestra attiva. Le applicazioni dannose potrebbero recuperare l\'intero contenuto della finestra ed esaminare tutto il testo, tranne le password."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupero di informazioni sulle finestre"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Consente a un\'applicazione di recuperare informazioni sulle finestre dalla gestione finestre. Le applicazioni dannose potrebbero recuperare informazioni destinate all\'utilizzo da parte del sistema interno."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtro eventi"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Consente a un\'applicazione di registrare un filtro di ingresso che filtra lo stream di tutti gli eventi degli utenti prima che vengano inviati. Un\'applicazione dannosa potrebbe controllare l\'interfaccia utente del sistema senza l\'intervento dell\'utente."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"chiusura parziale"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Mette il gestore delle attività in uno stato di chiusura. Non esegue una chiusura completa."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedire commutazione applicazione"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copia URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Seleziona testo"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selezione testo"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"aggiungi al dizionario"</string>
-    <string name="deleteText" msgid="7070985395199629156">"elimina"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Aggiungi al dizionario"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Elimina"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodo inserimento"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Azioni testo"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spazio di archiviazione in esaurimento"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sta inviando molti SMS. Vuoi consentire all\'applicazione di continuare a inviare messaggi?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Consenti"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nega"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Inviare SMS a codice breve?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Inviare SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vorrebbe inviare un messaggio di testo a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, che sembra essere un codice breve SMS.&lt;p&gt;L\'invio di messaggi di testo ad alcuni codici brevi potrebbe comportare l\'addebito di servizi premium sul tuo account per cellulari.&lt;p&gt;Vuoi consentire a questa applicazione di inviare il messaggio?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vorrebbe inviare un messaggio di testo a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, che è un codice breve SMS premium.&lt;p&gt;&lt;b&gt;L\'invio di un messaggio a questa destinazione comporterà l\'addebito di servizi premium sul tuo account per cellulari.&lt;/b&gt;&lt;p&gt;Vuoi consentire a questa applicazione di inviare il messaggio?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Invia messaggio"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Non inviare"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Segnala applicazione dannosa"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Scheda SIM rimossa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La rete mobile non sarà disponibile finché non eseguirai il riavvio con una scheda SIM valida inserita."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fine"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 416aa4e..f5a7e81 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"מאפשר ליישום לאחזר את המצב הפנימי של המערכת. יישומים זדוניים עלולים לאחזר מגוון רחב של מידע אישי ונתוני אבטחה, שעל פי רוב לעולם לא יזדקקו להם."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"אחזר את תוכן המסך"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"מאפשר ליישום לאחזר את התוכן של החלון הפעיל. יישומים זדוניים עלולים לאחזר את תוכן החלון כולו ולבחון את כל הטקסט שבו, מלבד סיסמאות."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"אחזר מידע חלון"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"מאפשר ליישום לאחזר מידע לגבי החלונות ממנהל החלונות. יישומים זדוניים עשויים לאחזר מידע המיועד לשימוש מערכת פנימי."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"סנן אירועים"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"מאפשר ליישום לרשום מסנן קלט שמסנן את הזרם של כל אירועי המשתמש לפני שהם נשלחים. יישום זדוני עשוי לשלוט ב-UI של המערכת ללא התערבות משתמש."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"כיבוי חלקי"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"מעביר את מנהל הפעילויות למצב כיבוי. לא מבצע כיבוי מלא."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומים"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"העתק כתובת אתר"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"בחר טקסט"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"בחירת טקסט"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"הוסף למילון"</string>
-    <string name="deleteText" msgid="7070985395199629156">"מחק"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"הוסף למילון"</string>
+    <string name="deleteText" msgid="6979668428458199034">"מחק"</string>
     <string name="inputMethod" msgid="1653630062304567879">"שיטת קלט"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"פעולות טקסט"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"שטח האחסון אוזל"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt; <xliff:g id="APP_NAME">%1$s</xliff:g> &lt;/ b&gt; שולח מספר רב של הודעות SMS. האם ברצונך לאפשר ליישום זה להמשיך לשלוח הודעות?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"אפשר"</string>
     <string name="sms_control_no" msgid="625438561395534982">"דחה"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"לשלוח SMS לקוד קצר?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"לשלוח SMS פרימיום?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt; <xliff:g id="APP_NAME">%1$s</xliff:g> &lt;/ b&gt; רוצה לשלוח הודעת טקסט אל &lt;b&gt; <xliff:g id="DEST_ADDRESS">%2$s</xliff:g> &lt;/ b&gt;, שנראה כמו קוד SMS קצר. &lt;p&gt; שליחת הודעות טקסט לקודים קצרים מסוימים עשויה לגרום לחיוב חשבון הנייד שלך בשירותי פרימיום. &lt;p&gt; האם ברצונך לאפשר ליישום זה לשלוח את ההודעה?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt; <xliff:g id="APP_NAME">%1$s</xliff:g> &lt;/ b&gt; רוצה לשלוח הודעת טקסט ל-&lt;b&gt; <xliff:g id="DEST_ADDRESS">%2$s</xliff:g> &lt;/ b&gt;, שהוא קוד פרימיום קצר של SMS. &lt;b&gt; &lt;p&gt; שליחת הודעה ליעד זה תגרום לחיוב חשבון הנייד שלך בשירותי פרימיום. &lt;/ b&gt; &lt;p&gt; האם ברצונך לאפשר ליישום זה לשלוח את ההודעה?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"שלח הודעה"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"אל תשלח"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"דווח על יישום זדוני"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"כרטיס ה-SIM הוסר"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"הרשת הסלולרית לא תהיה זמינה עד שתפעיל מחדש לאחר הכנסת כרטיס SIM חוקי."</string>
     <string name="sim_done_button" msgid="827949989369963775">"סיום"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index af28156..048cd49 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"システムの内部状態の取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、通常必要ないはずの各種の非公開/機密情報が取得される恐れがあります。"</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"画面のコンテンツの取得"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"作業中のウィンドウの内容を取得することをアプリに許可します。この許可を悪意のあるアプリに利用されると、ウィンドウの内容全体が取得されてパスワード以外のテキストがすべてチェックされる恐れがあります。"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ウィンドウ情報の取得"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"ウィンドウマネージャからウィンドウに関する情報を取得することをアプリに許可します。悪意のあるアプリが内部システムの利用を目的に情報を取得する恐れがあります。"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"イベントのフィルタリング"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"すべてのユーザーイベントが送られる前にストリームをフィルタリングする入力フィルタを登録することをアプリに許可します。悪意のあるアプリがユーザーの操作なしでシステムUIを制御する恐れがあります。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URLをコピー"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"テキストを選択"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"テキスト選択"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"辞書に追加"</string>
-    <string name="deleteText" msgid="7070985395199629156">"削除"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"辞書に追加"</string>
+    <string name="deleteText" msgid="6979668428458199034">"削除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"入力方法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"テキスト操作"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"空き容量わずか"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が大量のSMSメッセージを送信しています。このアプリにこのままメッセージの送信を許可しますか?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"許可する"</string>
     <string name="sms_control_no" msgid="625438561395534982">"許可しない"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"ショートコードへのSMSの送信"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"プレミアムSMSを送信しますか?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が、SMSショートコードと思われる&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;にテキストメッセージを送信しようとしています。&lt;p&gt;一部のショートコードにテキストメッセージを送信すると、プレミアムサービスの料金がモバイルアカウントが請求される場合があります。&lt;p&gt;このアプリにメッセージの送信を許可しますか?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が、プレミアムSMSショートコード&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;にテキストメッセージを送信しようとしています。&lt;p&gt;&lt;b&gt;この宛先にメッセージを送信すると、プレミアムサービスの料金がモバイルアカウントに請求されます。&lt;/b&gt;&lt;p&gt;このアプリにメッセージの送信を許可しますか?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"メッセージを送信"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"送信しない"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"悪意のあるアプリを報告"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIMカードが取り外されました"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"有効なSIMカードを挿入して再起動するまでは、モバイルネットワークは利用できません。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完了"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1f2a17f..1fbf600 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"앱이 시스템의 내부 상태를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인정보와 보안정보를 검색할 수 있습니다."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"화면 콘텐츠 검색"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"앱이 활성 창의 콘텐츠를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 전체 창의 콘텐츠를 검색하여 비밀번호를 제외한 모든 텍스트를 살펴볼 수 있습니다."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"창 관련 정보 가져오기"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"애플리케이션이 Window Manager에서 창 관련 정보를 가져오도록 허용합니다. 이 경우 악성 앱이 내부 시스템에서만 사용하도록 되어 있는 정보를 가져올 수 있습니다."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"일정 필터링"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"애플리케이션에 입력 필터를 등록할 수 있도록 하여 모든 사용자 일정 스트림을 전달하기 전에 필터링합니다. 이 경우 사용자의 개입 없이 악성 앱이 시스템 UI를 제어할 수 있습니다."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"부분 종료"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"작업 관리자를 종료 상태로 설정합니다. 전체 종료를 수행하지는 않습니다."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케이션 전환 방지"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL 복사"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"텍스트 선택"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"텍스트 선택"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"사전에 추가"</string>
-    <string name="deleteText" msgid="7070985395199629156">"삭제"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"사전에 추가"</string>
+    <string name="deleteText" msgid="6979668428458199034">"삭제"</string>
     <string name="inputMethod" msgid="1653630062304567879">"입력 방법"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"텍스트 작업"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"저장 공간이 부족함"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) SMS 메시지를 대량으로 보내고 있습니다. 해당 앱이 메시지를 계속 보내도록 하시겠습니까?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"허용"</string>
     <string name="sms_control_no" msgid="625438561395534982">"거부"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"SMS를 단축 코드로 보내시겠습니까?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"프리미엄 SMS를 보내시겠습니까?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) SMS 단축 코드로 추정되는 문자 메시지를 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(으)로 보내려 합니다.&lt;p&gt;문자 메시지를 단축 코드로 보내면 사용자의 모바일 계정에 프리미엄 서비스 요금이 청구될 수 있습니다.&lt;p&gt;해당 앱이 메시지를 보내도록 하시겠습니까?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) 문자 메시지를 프리미엄 SMS 단축 코드인 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(으)로 보내려 합니다.&lt;p&gt;&lt;b&gt;메시지를 보내면 사용자의 모바일 계정에 프리미엄 서비스 요금이 청구됩니다.&lt;/b&gt;&lt;p&gt;해당 앱이 메시지를 보내도록 하시겠습니까?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"메시지 보내기"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"보내지 않음"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"악성 앱 신고"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM 카드 제거됨"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"유효한 SIM 카드를 삽입하여 다시 시작할 때까지 모바일 네트워크를 사용할 수 없습니다."</string>
     <string name="sim_done_button" msgid="827949989369963775">"완료"</string>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 6db3a508..1cd9e74 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -69,11 +69,4 @@
         <item>@string/description_target_camera</item>
     </array>
 
-    <array name="lockscreen_chevron_drawables">
-        <item>@null</item>
-        <item>@drawable/ic_lockscreen_chevron_up</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 54badb6..9db7a4d 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Leidžiama programai nuskaityti vidinę sistemos būseną. Kenkėjiškos programos gali nuskaityti daug įvairios privačios ir saugios informacijos, kurios paprastai joms niekada neturėtų reikėti."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"nuskaityti ekrano turinį"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Leidžiama programai nuskaityti aktyvaus lango turinį. Kenkėjiškos programos gali bandyti išgauti viso lango turinį ir tirti visą jo tekstą, išskyrus slaptažodžius."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"gauti lango informaciją"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Leidžiama programai iš langų tvarkytuvės gauti informaciją apie langus. Kenkėjiškos programos gali gauti informaciją, kuri skirta naudoti sistemos viduje."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrų įvykiai"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Leidžiama programai registruoti įvesties filtrą, kuriuo filtruojamas visų naudotojo įvykių srautas prieš juos išsiunčiant. Kenkėjiška programa gali kontroliuoti sistemos naudotojo sąsają be naudotojo įsikišimo."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"dalinis išjungimas"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Veiklos tvarkyklę perjungia į išsijungimo būseną. Neišjungia visiškai."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopijuoti URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pasirinkti tekstą"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksto pasirinkimas"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"pridėti prie žodyno"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ištrinti"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Pridėti prie žodyno"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Ištrinti"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Įvesties būdas"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksto veiksmai"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Mažėja laisvos saugyklos vietos"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Naudojant &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siunčiama daug SMS pranešimų. Ar norite leisti šiai programai toliau siųsti pranešimus?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Leisti"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Uždrausti"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Siųsti SMS trumpuoju numeriu?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Siųsti brangesnį SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Naudojant &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prašoma išsiųsti teksto pranešimą &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, o tai yra trumpasis SMS numeris.&lt;p&gt;&lt;b&gt;Siųsdami pranešimus kai kuriais trumpaisiais numeriais galite būti apmokestinti mobiliojo ryšio sąskaitoje už brangesnes paslaugas.&lt;/b&gt;&lt;p&gt;Ar norite leisti šiai programai siųsti pranešimą?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Naudojant &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prašoma išsiųsti teksto pranešimą &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, o tai yra brangesnis trumpasis SMS numeris.&lt;p&gt;&lt;b&gt;Siųsdami pranešimą šiam gavėjui mobiliojo ryšio sąskaitoje būsite apmokestinti už brangesnes paslaugas.&lt;/b&gt;&lt;p&gt;Ar norite leisti šiai programai siųsti pranešimą?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Siųsti pranešimą"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nesiųsti"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Pranešti apie kenkėj. programą"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kortelė pašalinta"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilusis tinklas bus nepasiekiamas, kol nepaleisite iš naujo įdėję tinkamą SIM kortelę."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Atlikta"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 91d9415..fd24d2ab4 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Ļauj lietotnei izgūt sistēmas iekšējo statusu. Ļaunprātīgas lietotnes var izgūt dažādu privātu un drošu informāciju, kas parasti tām nav nepieciešama."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Ekrāna satura iegūšana"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ļauj lietotnei izgūt aktīva loga saturu. Ļaunprātīgas lietotnes var izgūt visu loga saturu un pārbaudīt visu tā tekstu, izņemot paroles."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Izgūt informāciju par logiem"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ļauj lietojumprogrammai no logu pārvaldnieka izgūt informāciju par logiem. Ļaunprātīgas lietotnes var izgūt informāciju, kas ir paredzēta iekšējai izmantošanai sistēmā."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"Filtrēt notikumus"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ļauj lietojumprogrammai reģistrēt ieejas filtru, kas filtrē visu lietotāja notikumu straumi, pirms notikumi tiek nosūtīti. Ļaunprātīga lietotne var kontrolēt sistēmas lietotāja saskarni, nejautājot lietotājam."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"daļēja izslēgšana"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Liek darbību pārvaldniekam pāriet izslēgšanas stāvoklī. Neveic pilnīgu izslēgšanu."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novērst lietojumprogrammu pārslēgšanu"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopēt URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Atlasīt tekstu"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksta atlase"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"pievienot vārdnīcai"</string>
-    <string name="deleteText" msgid="7070985395199629156">"dzēst"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Pievienot vārdnīcai"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Dzēst"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Ievades metode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksta darbības"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Paliek maz brīvas vietas"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sūta daudz īsziņu. Vai vēlaties, lai šī lietotne turpinātu sūtīt ziņojumus?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Atļaut"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Aizliegt"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Vai sūtīt īsziņu uz īso kodu?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vai nosūtīt īpašo īsziņu?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vēlas nosūtīt īsziņu uz adresi &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kas, iespējams, ir īsziņas īsais kods.&lt;p&gt;&lt;b&gt;Sūtot īsziņas uz dažiem īsajiem kodiem, no jūsu mobilā konta var tikt iekasēta maksa par paaugstinātas maksas pakalpojumiem.&lt;/b&gt;&lt;p&gt;Vai vēlaties atļaut šai lietotnei sūtīt šo ziņojumu?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vēlas nosūtīt īsziņu uz adresi &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kas, iespējams, ir paaugstinātas maksas īsziņas īsais kods.&lt;p&gt;&lt;b&gt;Sūtot ziņojumu uz šo galamērķi, no jūsu mobilā konta tiks iekasēta maksa par paaugstinātas maksas pakalpojumiem.&lt;/b&gt;&lt;p&gt;Vai vēlaties atļaut šai lietotnei sūtīt šo ziņojumu?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Sūtīt ziņojumu"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nesūtīt"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Ziņot par ļaunprātīgu lietotni"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM karte ir izņemta."</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilais tīkls nebūs pieejams līdz brīdim, kad restartēsiet ierīci ar ievietotu derīgu SIM karti."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gatavs"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5a49127..1719049 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Membenarkan apl untuk mendapatkan semula keadaan dalaman sistem. Apl hasad boleh mendapatkan pelbagai maklumat peribadi dan selamat yang biasanya tidak ia perlukan."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"dapatkan semula kandungan skrin"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Membenarkan apl untuk mendapatkan kandungan tetingkap aktif. Apl hasad boleh mengambil keseluruhan kandungan tetingkap dan memeriksa semua teks kecuali kata laluan."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"dapatkan maklumat tetingkap"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Membolehkan aplikasi mendapatkan maklumat tentang tetingkap dari pengurus tetingkap. Apl hasad boleh mendapatkan maklumat yang bertujuan untuk penggunaan sistem dalaman."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"tapis acara"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Membenarkan aplikasi mendaftarkan penapis input yang menapis strim semua acara pengguna sebelum dihantar. Apl hasad mungkin mengawal UI sistem tanpa campur tangan pengguna."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penutupan separa"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Meletakkan pengurus aktiviti dalam keadaan tutup. Tidak melaksanakan penutupan lengkap."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Salin URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pilih teks"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pemilihan teks"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"tambahkan pada kamus"</string>
-    <string name="deleteText" msgid="7070985395199629156">"padam"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Tambah ke kamus"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Padam"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Kaedah input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ruang storan semakin berkurangan"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sedang menghantar banyak mesej SMS. Adakah anda mahu membenarkan apl ini terus menghantar mesej?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Benarkan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nafikan"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Hantar SMS ke kod pendek?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Hantar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin menghantar mesej teks kepada &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang merupakan kod pendek SMS.&lt;p&gt;Menghantar mesej teks ke sesetengah kod pendek boleh menyebabkan akaun mudah alih anda dikenakan bayaran perkhidmatan premium.&lt;p&gt;Adakah anda mahu membenarkan apl ini menghantar mesej itu?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin menghantar mesej teks ke &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang merupakan kod pendek SMS premium.&lt;p&gt;&lt;b&gt;Menghantar mesej ke destinasi ini akan menyebabkan akaun mudah alih anda dikenakan bayaran untuk perkhidmatan premium.&lt;/b&gt;&lt;p&gt;Adakah anda mahu membenarkan apl ini menghantar mesej itu?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Hantar mesej"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Jangan hantar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Laporkan aplikasi hasad"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kad SIM dikeluarkan"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Rangkaian mudah alih tidak akan tersedia sehingga anda mula semula dengan kad SIM yang sah dimasukkan."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b94f399..cafdcd3 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Lar appen hente ut informasjon om systemets indre tilstand. Ondsinnede apper kan hente et bredt spekter av privat og sikker informasjon som de vanligvis aldri burde ha behov for."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hent av skjerminnhold"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lar appen hente ut innholdet i det aktive vinduet. Ondsinnede apper kan hente ut hele vindusinnholdet og undersøke all teksten, med unntak av passord."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hente vindusinformasjon"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lar appen hente informasjon om vinduene fra vindusbehandleren. Skadelige apper kan hente informasjon som ikke er ment for intern systembruk."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrere hendelser"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Lar appen registrere et inndatafilter som filtrerer strømmen for alle brukerhendelser før de sendes ut. Skadelige apper kan kontrollere brukergrensesnittet for systemet uten at brukeren gjør noe."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delvis avslutning"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre applikasjonsbytte"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopier URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Marker tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Merket tekst"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"legg til i ordliste"</string>
-    <string name="deleteText" msgid="7070985395199629156">"slett"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Legg til i ordlisten"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Slett"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Inndatametode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Lite ledig lagringsplass"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sender et stort antall SMS. Vil du la appen fortsette å sende ut meldinger?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Tillat"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Sperr"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Vil du sende SMS til kortkoden?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vil du sende premium-SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil sende en tekstmelding til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som ser ut til å være en SMS-kortkode.&lt;p&gt;Hvis du sender en melding til denne destinasjonen, kan mobilkontoen din komme til å belastes for premium-tjenester.&lt;p&gt;Vil du la denne meldingen sendes av appen?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil sende en tekstmelding til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som er en premium SMS-kortkode.&lt;p&gt;&lt;b&gt;Hvis du sender en melding til denne destinasjonen, belastes mobilkontoen din for premium-tjenester.&lt;/b&gt;&lt;p&gt;Vil du la denne meldingen sendes av appen?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send melding"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ikke send"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rapportér skadelig app"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort er fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile nettverket forblir utilgjengelig inntil du starter på nytt med et gyldig SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fullført"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0af5649..c6c4d5f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Hiermee kan de app de interne systeemstatus ophalen. Schadelijke apps kunnen een grote hoeveelheid persoonlijke en beveiligde informatie ophalen die ze normaal gesproken nooit nodig hebben."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"scherminhoud ophalen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Hiermee kan de app de inhoud van het actieve venster ophalen. Schadelijke apps kunnen de volledige inhoud van het venster ophalen en alle tekst bekijken, behalve wachtwoorden."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"venstergegevens ophalen"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Toestaan dat een app gegevens over vensters kan ophalen uit vensterbeheer. Schadelijke apps kunnen gegevens ophalen die zijn bedoeld voor interne systeemfunctionaliteit."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"evenementen filteren"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Toestaan dat een app een invoerfilter registreert waarmee de streams van alle gebruikersgebeurtenissen worden gefilterd voordat deze worden verzonden. Schadelijke apps kunnen de gebruikersinterface van het systeem beheren zonder tussenkomst van de gebruiker."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelijke uitschakeling"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen apps voorkomen"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL kopiëren"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Tekst selecteren"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstselectie"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"toevoegen aan woordenboek"</string>
-    <string name="deleteText" msgid="7070985395199629156">"verwijderen"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Toevoegen aan woordenboek"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Verwijderen"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Invoermethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstacties"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Opslagruimte is bijna vol"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; verzendt moment een groot aantal sms-berichten. Wilt u toestaan ​​dat deze app berichten blijft verzenden?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Toestaan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Weigeren"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Sms verzenden naar shortcode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Premium-sms verzenden?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil een sms-bericht verzenden naar &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Dit is waarschijnlijk een sms-shortcode.&lt;p&gt;Als u sms-berichten naar bepaalde shortcodes verzendt, worden mogelijk kosten voor premiumservices in rekening gebracht op uw mobiele account.&lt;p&gt;Wilt u toestaan dat deze app het bericht verzendt?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil een sms-bericht verzenden naar &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Dit is premium sms-shortcode.&lt;p&gt;&lt;b&gt;Als u een bericht naar deze bestemming verzendt, kosten voor premiumservices in rekening gebracht op uw mobiele account.&lt;/b&gt;&lt;p&gt;Wilt u toestaan dat deze app het bericht verzendt?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Bericht verzenden"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Niet verzenden"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Kwaadaardige app melden"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Simkaart verwijderd"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Het mobiele netwerk is niet beschikbaar totdat u het apparaat opnieuw start met een geldige simkaart."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gereed"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 229012b..89875e1 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Pozwala aplikacji na pobieranie wewnętrznego stanu systemu. Złośliwe aplikacje mogą pobrać szereg prywatnych i zabezpieczonych informacji, które normalnie nie są im potrzebne."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"pobieranie zawartości ekranu"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pozwala aplikacji na pobieranie zawartości aktywnego okna. Złośliwe aplikacje mogą pobrać całą zawartość okna i przeanalizować znajdujący się w nim tekst z wyjątkiem haseł."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"pobieranie informacji o oknach"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Zezwala aplikacji na pobieranie informacji o oknach z menedżera okien. Złośliwe aplikacje mogą pobierać informacje przeznaczone do użytku wewnętrznego w systemie."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrowanie zdarzeń"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Zezwala aplikacji na zarejestrowanie filtra wejściowego, który filtruje strumień wszystkich zdarzeń z udziałem użytkownika przed ich rozesłaniem. Złośliwe aplikacje mogą kontrolować interfejs systemu niezależnie od działań użytkownika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"częściowe wyłączenie"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Przełącza menedżera aktywności w stan wyłączenia. Nie wykonuje pełnego wyłączenia."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zapobieganie przełączaniu aplikacji"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiuj adres URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Zaznacz tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Zaznaczanie tekstu"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"dodaj do słownika"</string>
-    <string name="deleteText" msgid="7070985395199629156">"usuń"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Dodaj do słownika"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Usuń"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Sposób wprowadzania tekstu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Działania na tekście"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Kończy się miejsce"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wysyła wiele SMS-ów. Chcesz pozwolić tej aplikacji dalej wysyłać SMS-y?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Pozwól"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odmów"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Wysłać droższego SMS-a?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Wysłać droższego SMS-a?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce wysłać SMS-a pod numer &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, który wygląda na dodatkowo płatny.&lt;p&gt;Może to spowodować doliczenie do Twojego rachunku za komórkę opłaty za usługę dodatkową.&lt;p&gt;Chcesz pozwolić tej aplikacji na wysłanie SMS-a?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce wysłać SMS-a pod numer &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, który jest dodatkowo płatny.&lt;p&gt;&lt;b&gt;To spowoduje doliczenie do Twojego rachunku za komórkę opłaty za usługę dodatkową.&lt;/b&gt;&lt;p&gt;Chcesz pozwolić tej aplikacji na wysłanie SMS-a?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Wyślij wiadomość"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nie wysyłaj"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Zgłoś złośliwą aplikację"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM wyjęta"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Sieć komórkowa będzie niedostępna do chwili ponownego uruchomienia urządzenia z użyciem ważnej karty SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gotowe"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6f8616a..cc5ece7 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que a aplicação obtenha o estado interno do sistema. As aplicações maliciosas podem obter uma ampla variedade de dados privados e seguros de que, normalmente, nunca devem necessitar."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"obter o conteúdo do ecrã"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que a aplicação obtenha o conteúdo da janela ativa. As aplicações maliciosas podem obter todo o conteúdo da janela e examinar todo o texto, exceto as palavras-passe."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"obter informações da janela"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que uma aplicação obtenha informações sobre as janelas a partir do gestor de janelas. Aplicações maliciosas podem obter informações que se destinam à utilização interna do sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que uma aplicação registe um filtro de entrada que filtra a transmissão em fluxo contínuo para todos os eventos de utilizador antes de serem entregues. Uma aplicação maliciosa pode controlar a IU do sistema sem intervenção do utilizador."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"encerramento parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gestor de actividade num estado de encerramento. Não executa um encerramento completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir trocas de aplicações"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selecionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecção de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"adicionar ao dicionário"</string>
-    <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Adicionar ao dicionário"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acções de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Está quase sem espaço de armazenamento"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; está a enviar um grande número de mensagens SMS. Pretende autorizar que a aplicação continue a enviar mensagens?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Recusar"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Enviar SMS ao código pequeno?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pretende enviar um SMS para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que parece ser um código SMS pequeno.&lt;p&gt;Enviar esta mensagem a alguns códigos pequenos pode fazer com que sejam faturados serviços premium na sua conta de telemóvel.&lt;p&gt;Pretende autorizar que a aplicação envie a mensagem?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pretende enviar um SMS a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que é um pequeno código de SMS premium.&lt;p&gt;&lt;b&gt;Enviar uma mensagem para este destino irá fazer com que sejam faturados serviços premium na sua conta de telemóvel.&lt;/b&gt;&lt;p&gt;Pretende autorizar que a aplicação envie a mensagem?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensagem"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Não enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Comunicar aplicação maliciosa"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A rede de telemóvel estará indisponível até que reinicie o aparelho com um cartão SIM válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4bd669c..df74588 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que o aplicativo recupere o estado interno do sistema. Aplicativos maliciosos podem obter uma grande variedade de informações privadas e seguras que eles normalmente não precisariam."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar conteúdo da tela"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que o aplicativo recupere o conteúdo da janela ativa. Aplicativos maliciosos podem recuperar o conteúdo da janela inteira e examinar todo o texto, exceto as senhas."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar informações de janelas"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que o aplicativo recupere informações sobre as janelas do gerenciador de janelas. Aplicativos mal-intencionados podem recuperar informações destinadas ao uso interno do sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que o aplicativo registre um filtro de entrada que filtra o fluxo de todos os eventos do usuário antes que sejam enviados. Aplicativos mal-intencionados podem controlar a interface do sistema sem a intervenção do usuário."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"desligamento parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gerenciador de atividades em um estado de desligamento. Não executa o desligamento completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar trocas de aplicativo"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selecionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Seleção de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"adicionar ao dicionário"</string>
-    <string name="deleteText" msgid="7070985395199629156">"excluir"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Adicionar ao dicionário"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Excluir"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ações de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Pouco espaço de armazenamento"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envia uma grande quantidade de mensagens SMS. Deseja permitir que este aplicativo continue enviando mensagens?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Negar"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Enviar SMS para código curto?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; deseja enviar uma mensagem de texto para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que parece ser um código curto SMS.&lt;p&gt;O envio de mensagens de texto a alguns códigos curtos pode fazer com que a conta seja cobrada por serviços premium.&lt;p&gt;Deseja permitir que este aplicativo envie a mensagem?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; deseja enviar uma mensagem de texto para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que é um código curto SMS premium.&lt;p&gt;&lt;b&gt;O envio de uma mensagem a esse destino fará com que a conta seja cobrada por serviços premium.&lt;/b&gt;&lt;p&gt;Deseja permitir que este aplicativo envie a mensagem?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensagem"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Não enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Denunciar aplicativo malicioso"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um cartão SIM válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index a00934d..a9eafdb 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -339,6 +339,14 @@
     <skip />
     <!-- no translation found for permdesc_retrieve_window_content (3193269069469700265) -->
     <skip />
+    <!-- no translation found for permlab_retrieve_window_info (8532295199112519378) -->
+    <skip />
+    <!-- no translation found for permdesc_retrieve_window_info (4998836370424186849) -->
+    <skip />
+    <!-- no translation found for permlab_filter_events (8675535648807427389) -->
+    <skip />
+    <!-- no translation found for permdesc_filter_events (8006236315888347680) -->
+    <skip />
     <string name="permlab_shutdown" msgid="7185747824038909016">"serrar parzialmain"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Metta l\'administratur dad activitads en in stadi da pausa. El na vegn betg serrà dal tut."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar il midar tranter applicaziuns"</string>
@@ -1414,9 +1422,9 @@
     <!-- no translation found for selectTextMode (1018691815143165326) -->
     <skip />
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecziun da text"</string>
-    <!-- no translation found for addToDictionary (9090375111134433012) -->
+    <!-- no translation found for addToDictionary (4352161534510057874) -->
     <skip />
-    <!-- no translation found for deleteText (7070985395199629156) -->
+    <!-- no translation found for deleteText (6979668428458199034) -->
     <skip />
     <string name="inputMethod" msgid="1653630062304567879">"Metoda d\'endataziun"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acziuns da text"</string>
@@ -1576,6 +1584,20 @@
     <skip />
     <!-- no translation found for sms_control_no (625438561395534982) -->
     <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <!-- no translation found for sim_removed_title (6227712319223226185) -->
     <skip />
     <!-- no translation found for sim_removed_message (2333164559970958645) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 59acfe1..537cb20 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite aplicaţiei să preia starea internă a sistemului. Aplicaţiile rău intenţionate pot să preia o gamă variată de informaţii private şi securizate, de care în mod normal nu ar avea nevoie niciodată."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"preia conţinutul de pe ecran"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite aplicaţiei să preia conţinutul ferestrei active. Aplicaţiile rău intenţionate pot să preia întregul conţinut al ferestrei şi să examineze integral textul acesteia, cu excepţia parolelor."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"preluare informaţii despre ferestre"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite unei aplicaţii să preia informaţii despre ferestrele din managerul de ferestre. Aplicaţiile rău intenţionate pot prelua informaţii care sunt destinate utilizării sistemului intern."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrare evenimente"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite unei aplicaţii să înregistreze un filtru de intrare, care filtrează transmiterea în flux a tuturor evenimentelor utilizatorilor înainte ca acestea să fie expediate. Aplicaţiile rău intenţionate pot controla interfaţa de utilizare a sistemului fără intervenţia utilizatorului."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"închidere parţială"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Plasează Managerul de activităţi într-o stare de închidere. Nu efectuează o închidere completă."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiaţi adresa URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selectaţi text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selectare text"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"adăugaţi în dicţionar"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ştergeţi"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Adăugaţi în dicţionar"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Ştergeţi"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodă de intrare"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acţiuni pentru text"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spaţiul de stocare aproape ocupat"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; trimite un număr mare de mesaje SMS. Permiteţi acestei aplicaţii să trimită în continuare mesaje?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permiteţi"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Refuzaţi"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Trimiteţi SMS la codul scurt?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Trimiteţi SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; intenţionează să trimită un mesaj text la &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, care pare a fi un cod scurt SMS.&lt;p&gt;Trimiterea de mesaje text la unele coduri scurte poate determina taxarea contului dvs. mobil pentru servicii premium.&lt;p&gt;Permiteţi acestei aplicaţii să trimită mesajul?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; intenţionează să trimită un mesaj text la &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, care este un cod scurt SMS premium.&lt;p&gt;&lt;b&gt;Trimiterea unui mesaj la această destinaţie va determina taxarea contului dvs. mobil pentru servicii premium.&lt;/b&gt;&lt;p&gt;Permiteţi acestei aplicaţii să trimită mesajul?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Trimiteţi mesajul"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nu trimiteţi"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Raport. aplic.rău intenţionată"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Card SIM eliminat"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Reţeaua mobilă va fi indisponibilă până când reporniţi cu o cartelă SIM validă introdusă."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Terminat"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ea69d45..50670fe 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Приложение сможет получать данные о внутреннем состоянии системы. Вредоносные программы смогут получать личную и защищенную информацию, к которой у них не должно быть доступа."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"получать доступ к содержанию экрана"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Приложение сможет получать контент активного окна. Вредоносные программы смогут перехватывать такой контент и анализировать любой текст, кроме паролей."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"доступ к информации в окне"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Открывает приложению доступ к информации из диспетчера окон. Обратите внимание, что вредоносное ПО может получить доступ к некоторой системной информации устройства."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"Фильтрация событий"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешает приложению зарегистрировать входной фильтр, который анализирует весь поток пользовательских событий. Обратите внимание, что вредоносное ПО может получить доступ к управлению интерфейсом без ведома пользователя."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частичное завершение работы"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Завершает работу диспетчера активности. Не выполняет полное завершение работы."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запретить переключение приложений"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копировать URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Выбрать текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Выбор текста"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"добавить в словарь"</string>
-    <string name="deleteText" msgid="7070985395199629156">"удалить"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Добавить в словарь"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Удалить"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Способ ввода"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Операции с текстом"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Заканчивается свободное место"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; отправляет большое количество SMS. Разрешить приложению и дальше отправлять сообщения?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Разрешить"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Запретить"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Отправить SMS?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Отправить SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; собирается отправить SMS-сообщение на короткий номер &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;&lt;p&gt; За отправку сообщений на некоторые короткие номера с вашего счета могут списываться дополнительные средства.&lt;p&gt;Разрешить отправку?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; собирается отправить SMS на короткий номер &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;.&lt;p&gt;&lt;b&gt; Если это произойдет, с вашего счета будут списаны дополнительные средства.&lt;/b&gt;&lt;p&gt;Разрешить отправку?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Отправить сообщение"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не отправлять"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Сообщить о вредоносном ПО"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта удалена"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 165f1ed..3488b61 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Umožňuje aplikácii načítať interný stav systému. Škodlivé aplikácie môžu načítať široký rozsah súkromných a zabezpečených informácií, ktoré by obvykle nemali nikdy potrebovať."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"načítanie obsahu obrazovky"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikácii načítať obsah aktívneho okna. Škodlivé aplikácie môžu získať celý obsah okna a preskúmať celý jeho text okrem hesiel."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítanie informácií o oknách"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikácii načítať informácie o oknách zo správcu okien. Škodlivé aplikácie môžu načítať informácie, ktoré sú určené pre interné využitie systému."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrovanie udalostí"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožňuje aplikácii zaregistrovať vstupný filter, ktorý filtruje stream všetkých prenosov používateľa pred ich odvysielaním. Škodlivá aplikácia môže bez zásahu používateľa ovládať používateľské rozhranie systému."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Čiastočné vypnutie"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvedie správcu činností do vypnutého stavu. Úplné vypnutie však nenastane."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Skopírovať adresu URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Vybrať text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Výber textu"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"pridať do slovníka"</string>
-    <string name="deleteText" msgid="7070985395199629156">"odstrániť"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Pridať do slovníka"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Odstrániť"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metóda vstupu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operácie s textom"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nedostatok ukladacieho priestoru"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; posiela veľký počet správ SMS. Chcete tejto aplikácií povoliť, aby aj naďalej posielala správy?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Povoliť"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odmietnuť"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Odoslať SMS na skrátené číslo?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Odoslať prémiovú správu SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odoslať textovú správu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ktoré sa zdá byť skráteným číslom SMS.&lt;p&gt;Odoslanie správy na skrátené číslo môže spôsobiť, že na účet vášho mobilného zariadenia budú účtované poplatky za prémiové služby.&lt;p&gt;Chcete aplikácií povoliť túto správu odoslať?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odoslať textovú správu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ktoré je prémiovým skráteným číslom SMS.&lt;p&gt;&lt;b&gt;Odoslanie správy na toto číslo spôsobí, že na účet vášho mobilného zariadenia budú účtované poplatky za prémiové služby.&lt;/b&gt;&lt;p&gt;Chcete aplikácii povoliť túto správu odoslať?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Odoslať správu"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Neodoslať"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Nahlásiť škodlivú aplikáciu"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM bola odobraná"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilná sieť nebude k dispozícii, kým nevložíte platnú kartu SIM a zariadenie nereštartujete."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 46cbcdb..b25e3d4 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Programu omogoča prejemanje notranjega stanja sistema. Zlonamerni programi lahko na ta način dobijo različne zasebne in varnostne podatke, ki jih običajno ne potrebujejo."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"prenos vsebine zaslona"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Programu omogoča dostop do vsebine aktivnega okna. Zlonamerni programi lahko dobijo vso vsebino okna in pregledajo njeno besedilo razen gesel."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"prenos podatkov o oknih"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Omogoča, da aplikacija iz upravitelja oken pridobiva podatke o oknih. Zlonamerne aplikacije lahko pridobivajo podatke, namenjene za notranjo uporabo v sistemu."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje dogodkov"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Omogoča, da aplikacija registrira vhodni filter, ki pred razpošiljanjem filtrira tok vseh uporabniških dogodkov. Zlonamerne aplikacije lahko nadzirajo uporabniški vmesnik sistema brez posega uporabnika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delna zaustavitev"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Upravitelja dejavnosti preklopi v stanje za zaustavitev. Ne izvede celotne zaustavitve."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiraj URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Izbira besedila"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Izbrano besedilo"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"dodaj v slovar"</string>
-    <string name="deleteText" msgid="7070985395199629156">"izbriši"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Dodaj v slovar"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način vnosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Besedilna dejanja"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Prostor za shranjevanje bo pošel"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pošilja veliko SMS-ov. Ali želite dovoliti, da jih še naprej pošilja?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Dovoli"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Zavrni"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Pošljem SMS na kratko štev.?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Pošljem SMS za plačlj. stor.?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati SMS na številko &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kar je videti kot kratka številka za plačljive storitve SMS.&lt;p&gt;S pošiljanjem sporočil na to številko bo vaš račun za mobilni telefon bremenjen za plačljive storitve.&lt;p&gt;Ali želite aplikaciji dovoliti, da pošlje sporočilo?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati SMS na številko &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kar je kratka številka za plačljive storitve SMS.&lt;p&gt;&lt;b&gt;S pošiljanjem sporočil na to številko bo vaš račun za mobilni telefon bremenjen za plačljive storitve.&lt;/b&gt;&lt;p&gt;Ali želite aplikaciji dovoliti, da pošlje sporočilo?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Pošlji sporočilo"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ne pošlji"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Prijavi zlonamerno aplikacijo"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kartica SIM odstranjena"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilno omrežje ne bo na voljo, dokler naprave vnovič ne zaženete z veljavno kartico SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Dokončano"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fd337a3..0195968 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Дозвољава апликацији да преузме интерни статус система. Злонамерне апликације могу да преузимају разноврсне приватне и заштићене информације које им обично нису потребне."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"преузимање садржаја екрана"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дозвољава апликацији да преузме садржај активног прозора. Злонамерне апликације могу да преузму цео садржај прозора и прегледају целокупан текст, осим лозинки."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"преузимање информација о прозорима"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Омогућава апликацији да преузме информације о прозорима од менаџера прозора. Злонамерне апликације могу да преузму информације које су намењене за интерну употребу система."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"филтрирање догађаја"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Омогућава апликацији да региструје филтер улазног садржаја који филтрира стрим свих догађаја корисника пре њиховог слања. Злонамерна апликација може да контролише кориснички интерфејс система без интервенције корисника."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"делимично искључивање"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ставља менаџера активности у стање искључивања. Не искључује га у потпуности."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копирај URL адресу"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Изабери текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Избор текста"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"додај у речник"</string>
-    <string name="deleteText" msgid="7070985395199629156">"избриши"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Додај у речник"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Избриши"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Простор за складиштење је на измаку"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; шаље велики број SMS порука. Желите ли да дозволите овој апликацији да настави са слањем порука?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Дозволи"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Одбиј"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Пошаљи SMS на кратак кôд?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Желите да пошаљете премијум SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жели да вам пошаље текстуалну поруку на адресу &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, која можда представља кратак кôд SMS-а.&lt;p&gt;Слање порука на неке кратке кодове може да се наплаћује као премијум услуга са налога за мобилни уређај.&lt;p&gt;Желите ли да дозволите овој апликацији да пошаље поруку?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жели да вам пошаље текстуалну поруку на адресу &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, која представља кратак кôд премијум SMS-а.&lt;p&gt;&lt;b&gt;Ако се пошаље порука на ово одредиште, биће вам наплаћена премијум услуга са налога за мобилни уређај.&lt;/b&gt;&lt;p&gt;Желите ли да дозволите овој апликацији да пошаље поруку?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Пошаљи поруку"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не шаљи"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Пријави злонамерну апликацију"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM картица је уклоњена"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мобилна мрежа неће бити доступна док не покренете систем поново уз уметање важеће SIM картице."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ebe61a2..31d63397 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Tillåter att appen hämtar systemets interna status. Skadliga appar kan hämta privat och skyddad information som normalt aldrig ska behövas."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hämta skärminnehåll"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillåter att appen hämtar innehållet i det aktiva fönstret. Skadliga appar kan hämta allt innehåll i fönstret och läsa all text utom lösenord."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hämta information om fönster"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Tillåter att appen hämtar information om fönstren från fönsterhanteraren. Skadliga appar kan hämta information som är avsedd för användning i det interna systemet."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrera händelser"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Tillåter att appen registrerar indatafilter som filtrerar flödet med användarhändelser innan de skickas. Skadliga appar kan styra systemets användargränssnitt utan att användaren gör något."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"avsluta delvis"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Sätter aktivitetshanteraren i avstängningsläge. Utför inte en fullständig avstängning."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"förhindrar programbyten"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiera webbadress"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Markera text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Textmarkering"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"lägg till i ordlista"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ta bort"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Lägg till i ordlista"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Ta bort"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Indatametod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textåtgärder"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Lagringsutrymmet börjar ta slut"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; skickar ett stort antal SMS. Vill du tillåta att appen fortsätter att skicka meddelanden?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Tillåt"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Neka"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Skicka SMS till kortkod?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Skicka premium-SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vill skicka ett SMS till &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; som verkar vara en kortkod för SMS.&lt;p&gt;När du skickar SMS till kortkoder kan mobilkontot debiteras för premiumtjänster.&lt;p&gt;Vill du tillåta att appen skickar meddelandet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vill skicka ett SMS till &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; som är en kortkod för SMS.&lt;p&gt;&lt;b&gt;Om du skickar ett meddelande till den här mottagaren kommer ditt mobilkonto att debiteras för premiumtjänster.&lt;/b&gt;&lt;p&gt;Vill du tillåta att appen skickar meddelandet?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Skicka meddelande"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Skicka inte"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rapportera skadlig app"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortet togs bort"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobila nätverket kommer inte att vara tillgängligt förrän du startar om med ett giltigt SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Klar"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c2bd3ee..6fb20dd 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Inaruhusu programu kutoa hali ya ndani ya mfumo. Programu hasidi zinaweza kutoa aina nyingi za taarifa za faragha na salama ambazo kwa kawaida hazihitaji."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"epua maudhui ya skrini"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Inaruhusu programu kutoa maudhui ya dirisha amilifu. Programu hasidi zinaweza kutoa maudhui yote ya dirisha na kuchunguza maandishi yake yote isipokuwa nenosiri."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"okoa maelezo ya dirisha"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Huruhusu programu kuokoa maelezo kuhusu madirisha kutoka kwenye kidhibiti dirisha. Huenda programu hasidi ikakusanya maelezo ambayo yamekusudiwa kwa matumizi ya mfumo wa ndani."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"chuja matukio"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Huruhusu programu kusajili kichujio ingizo kinachochuja mkondo wa matukio ya mtumiaji kabla ya kutumwa. Huenda programu hasidi ikadhibiti mfumo wa UI bila mtumiaji kuingilia kati."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Zima nusu"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Huweka kisimamia shughuli katika hali ya kuzima. Haiadhiri uzimaji kamili"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string>
@@ -470,8 +474,8 @@
     <string name="permlab_getAccounts" msgid="1086795467760122114">"pata akaunti kwenye kifaa"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa kompyuta kibao. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa simu. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string>
-    <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"unda akaunti na weka manenosiri"</string>
-    <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Inaruhusu programu kutumia uwezo wa uthibitishaji akaunti wa KidhibitiAkaunti, pamoja na kuunda akaunti na kupata na kuweka nywila zao."</string>
+    <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"fungua akaunti na weka manenosiri"</string>
+    <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Inaruhusu programu kutumia uwezo wa uthibitishaji akaunti wa KidhibitiAkaunti, ikiwa ni pamoja na kufungua akaunti na kupata na kuweka manenosiri ya akaunti hizo."</string>
     <string name="permlab_manageAccounts" msgid="4983126304757177305">"ongeza au uondoe akaunti"</string>
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Inaruhusu programu kutekeleza shughuli kama vile kuongeza na kutoa akaunti, na kufuta manenosiri yazo."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"tumia akaunti kwenye kifaa"</string>
@@ -737,7 +741,7 @@
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Jina la mtumiaji (barua pepe)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Nenosiri"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ingia"</string>
-    <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Jina batili la mtumiaji au nywila"</string>
+    <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Jina la mtumiaji au nenosiri batili."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Umesahau jina lako la mtumiaji au nenosiri?"\n"Tembela "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Inakagua..."</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"Fungua"</string>
@@ -901,7 +905,7 @@
     <string name="day" msgid="8144195776058119424">"siku"</string>
     <string name="days" msgid="4774547661021344602">"siku"</string>
     <string name="hour" msgid="2126771916426189481">"saa"</string>
-    <string name="hours" msgid="894424005266852993">"masaa"</string>
+    <string name="hours" msgid="894424005266852993">"saa"</string>
     <string name="minute" msgid="9148878657703769868">"dakika"</string>
     <string name="minutes" msgid="5646001005827034509">"Dakika"</string>
     <string name="second" msgid="3184235808021478">"sekunde"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Nakili URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Chagua maandishi"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Uchaguzi wa maandishi?"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"ongeza kwa kamusi"</string>
-    <string name="deleteText" msgid="7070985395199629156">"futa"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Ongeza kwenye kamusi"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Futa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mbinu ya uingizaji"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Vitendo vya maandishi"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nafasi ya kuhafadhi inakwisha"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; inatuma idadi kubwa ya jumbe za SMS. Je, unataka kuruhusu programu hii kuendelea kutuma jumbe?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Ruhusu"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Kataza"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Tuma SMS kwa msimbo mfupi?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Tuma SMS ya ada?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ingependa kutuma ujumbe kwa  &lt;b&gt;i<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ambayo inaonekana kama msimbo mfupi wa ujumbe mfupi.&lt;p&gt;Kutuma ujumbe mfupi kwa baadhi ya misimbo mifupi kunaweza kusababisha akaunti yako ya simu kulipishwa huduma ya ada.&lt;p&gt;Je, unataka kuruhusu programu hii kutuma ujumbe?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingetaka kutuma ujumbe wa maandishi kwa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ambayo ni msimbo mfupi wa SMS ya ada.&lt;p&gt;&lt;b&gt;Kutuma ujumbe mahali hapa kutasababisha akaunti yako ya simu kulipishwa kwa huduma ya ada.&lt;/b&gt;&lt;p&gt;Je, unataka kuruhusu programu hii kutuma ujumbe?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Tuma ujumbe"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Usitume"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Ripoti programu hasidi"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
diff --git a/core/res/res/values-sw720dp-land/arrays.xml b/core/res/res/values-sw720dp-land/arrays.xml
deleted file mode 100644
index d845875..0000000
--- a/core/res/res/values-sw720dp-land/arrays.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
-</resources>
diff --git a/core/res/res/values-sw720dp-port/arrays.xml b/core/res/res/values-sw720dp-port/arrays.xml
deleted file mode 100644
index d845875..0000000
--- a/core/res/res/values-sw720dp-port/arrays.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
-</resources>
diff --git a/core/res/res/values-sw720dp/styles.xml b/core/res/res/values-sw720dp/styles.xml
index 640e898..fee1c24f 100644
--- a/core/res/res/values-sw720dp/styles.xml
+++ b/core/res/res/values-sw720dp/styles.xml
@@ -16,8 +16,8 @@
 
 <resources>
     <style name="PreferencePanel">
-        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginStart">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginEnd">@dimen/preference_screen_side_margin</item>
         <item name="android:layout_marginTop">@dimen/preference_screen_top_margin</item>
         <item name="android:layout_marginBottom">@dimen/preference_screen_bottom_margin</item>
         <item name="android:background">?attr/detailsElementBackground</item>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 976ff8a..32f6aea 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"อนุญาตให้แอปพลิเคชันเรียกดูสถานะภายในของระบบ แอปพลิเคชันที่เป็นอันตรายอาจเรียกดูข้อมูลส่วนบุคคลและข้อมูลที่ต้องรักษาความปลอดภัยหลากหลายประเภทที่ปกติแล้วไม่จำเป็นต้องใช้แต่อย่างใด"</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ดึงเนื้อหาหน้าจอ"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"อนุญาตให้แอปพลิเคชันดึงเนื้อหาของหน้าต่างที่ใช้งานอยู่ แอปพลิเคชันที่เป็นอันตรายอาจดึงเนื้อหาจากหน้าต่างทั้งหมดและตรวจสอบข้อความทั้งหมดยกเว้นรหัสผ่าน"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"เรียกข้อมูลหน้าต่าง"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับหน้าต่างจากเครื่องมือจัดการหน้าต่าง แอปพลิเคชันที่เป็นอันตรายอาจดึงข้อมูลที่มีไว้เพื่อการใช้ของระบบภายใน"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"กรองกิจกรรม"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"อนุญาตให้แอปพลิเคชันลงทะเบียนตัวกรองข้อมูลซึ่งจะกรองสตรีมกิจกรรมทั้งหมดของผู้ใช้ก่อนที่จะทำการเผยแพร่ออกไป แอปพลิเคชันที่เป็นอันตรายอาจควบคุม UI ของระบบโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ปิดการทำงานบางส่วน"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"กำหนดให้ตัวจัดการกิจกรรมอยู่ในสถานะปิดระบบ โดยไม่ได้ปิดระบบอย่างสมบูรณ์"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"คัดลอก URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"เลือกข้อความ"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"การเลือกข้อความ"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"เพิ่มลงในพจนานุกรม"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ลบ"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"เพิ่มในพจนานุกรม"</string>
+    <string name="deleteText" msgid="6979668428458199034">"ลบ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"วิธีป้อนข้อมูล"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"การทำงานของข้อความ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"พื้นที่จัดเก็บเหลือน้อย"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; กำลังส่งข้อความ SMS จำนวนมาก คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความต่อหรือไม่"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"อนุญาต"</string>
     <string name="sms_control_no" msgid="625438561395534982">"ปฏิเสธ"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"ส่ง SMS เป็นรหัสสั้นหรือไม่"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"ส่ง SMS พรีเมียมหรือไม่"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ต้องการส่งข้อความให้กับ &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; ซึ่งเป็น SMS รหัสสั้น&lt;p&gt;การส่งข้อความเป็นรหัสสั้นบางอย่างอาจทำให้มีการเรียกเก็บเงินในบัญชีมือถือของคุณสำหรับบริการพรีเมียม&lt;p&gt;คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความหรือไม่"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ต้องการส่งข้อความให้กับ &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; ซึ่งเป็น SMS รหัสสั้นแบบพรีเมียม&lt;p&gt;&lt;b&gt;การส่งข้อความไปยังปลายทางนี้จะทำให้มีการเรียกเก็บเงินในบัญชีมือถือของคุณสำหรับบริการพรีเมียม&lt;/b&gt;&lt;p&gt;คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความหรือไม่"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"ส่งข้อความ"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"ไม่ส่ง"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"รายงานแอปที่เป็นอันตราย"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"นำซิมการ์ดออกแล้ว"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"เครือข่ายมือถือจะไม่สามารถใช้งานได้จนกว่าคุณจะรีสตาร์ทโดยใส่ซิมการ์ดที่ถูกต้องแล้ว"</string>
     <string name="sim_done_button" msgid="827949989369963775">"เสร็จสิ้น"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e9ea129..1d33c75 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Pinapayagan ang app na mabawi ang panloob na katayuan ng system. Maaaring bawiin ng nakakahamak na apps ang iba\'t ibang pribado at secure na impormasyon na hindi kailanman normal na kinakailangan ng mga ito."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"kunin ang nilalaman ng screen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pinapayagan ang app na bawiin ang nilalaman ng aktibong window. Maaaring bawiin ng nakakahamak na apps ang kabuuang nilalaman ng window at suriin ang lahat ng teksto nito maliban sa mga password."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"kunin ang impormasyon ng window"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Pinapayagan ang application na kumuha ng impormasyon tungkol sa mga window mula sa tagapamahala ng window. Maaaring kumuha ang mga nakakahamak na app ng impormasyong nilayon para sa panloob na paggamit ng system."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"i-filter ang mga kaganapan"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Pinapayagan ang isang application na magrehistro ng filter ng input na nagpi-filter sa stream ng lahat ng kaganapan ng user bago maipadala ang mga iyon. Maaaring kontrolin ng nakakahamak na app ang system UI nang hindi nakikialam ang user."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"bahagyang pag-shutdown"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Inilalagay ang tagapamahala ng aktibidad sa katayuan ng pag-shutdown. Hindi nagsasagawa ng kumpletong pag-shutdown."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopyahin ang URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pumili ng teksto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pagpili ng teksto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"idagdag sa diksyunaryo"</string>
-    <string name="deleteText" msgid="7070985395199629156">"tanggalin"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Idagdag sa diksyunaryo"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Tanggalin"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Pamamaraan ng pag-input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Pagkilos ng teksto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nauubusan na ang puwang ng storage"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ay nagpapadala ng maraming mensaheng SMS. Gusto mo bang payagan ang app na ito na magpatuloy sa pagpapadala ng mga mensahe?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Payagan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Tanggihan"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Magpadala SMS sa short code?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Ipadala ang premium na SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ay gustong magpadala ng text message sa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, na lumilitaw na isang SMS na short code.&lt;p&gt;Ang pagpapadala ng mga text message sa ilang short code ay maaaring magdulot ng pagsingil sa iyong mobile account para sa mga premium na serbisyo.&lt;p&gt;Gusto mo bang payagan ang app na ito na ipadala ang mensahe?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ay gustong magpadala ng text message sa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, na isang premium na SMS na short code.&lt;p&gt;&lt;b&gt;Ang pagpapadala ng mensahe sa patutunguhang ito ay magdudulot ng pagsingil sa iyong mobile account para sa mga premium na serbisyo.&lt;/b&gt;&lt;p&gt;Gusto mo bang payagan ang app na ito na ipadala ang mensahe?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Ipadala ang mensahe"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Huwag ipadala"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Mag-ulat ng nakakapahamak na app"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Naalis ang SIM card"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Hindi magiging available ang mobile network hanggang mag-restart ka gamit ang isang may-bisang SIM card"</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tapos na"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 1259bd5..75c3e31 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Uygulamaya, sistemin iç durumunu alma izni verir. Kötü amaçlı uygulamalar normalde gerek duymadıkları çok çeşitli özel ve güvenli bilgilerini alabilir."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ekran içeriğini al"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Uygulamaya, etkin pencerenin içeriğini alma izni verir. Kötü amaçlı uygulamalar tüm pencere içeriğini alabilir ve şifreleri hariç tüm metni inceleyebilir."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"pencere bilgilerini al"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Uygulamaya, pencere yöneticisinden pencerelerle ilgili bilgi alma izni verir. Zararlı uygulamalar dahili sistem kullanımına yönelik bilgileri alabilir."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"etkinlikleri filtrele"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Uygulamaya, tüm kullanıcı etkinlikleri dağıtılmadan önce ilgili akışa filtre uygulayan bir giriş filtresi kaydetme izni verir. Zararlı uygulamalar kullanıcı müdahalesi olmadan sistem arayüzünü denetleyebilir."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"kısmi kapatma"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Eylem yöneticisini kapalı duruma getirir. Tam kapatma işlemi gerçekleştirmez."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"uygulama değişimlerini engelle"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL\'yi kopyala"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Metin seç"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Metin seçimi"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"sözlüğe ekle"</string>
-    <string name="deleteText" msgid="7070985395199629156">"sil"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Sözlüğe ekle"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Sil"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Giriş yöntemi"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Metin eylemleri"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Depolama alanı bitiyor"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; çok sayıda SMS mesajı gönderiyor. Bu uygulamanın mesaj göndermeye devam etmesine izin veriyor musunuz?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"İzin ver"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Reddet"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Kısa koda SMS gönderilsin mi?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Premium SMS gönderilsin mi?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, SMS kısa koduna sahip olduğu anlaşılan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; hedefine bir kısa mesaj göndermek istiyor.&lt;p&gt;Bazı kısa kodlara kısa mesaj göndermek mobil hesabınızın premium hizmetle faturalandırılmasına neden olabilir.&lt;/b&gt;&lt;p&gt;Bu uygulamanın mesaj göndermesine izin vermek istiyor musunuz?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; premium SMS kısa koduna sahip &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; hedefine kısa mesaj göndermek istiyor.&lt;p&gt;&lt;b&gt;Bu hedefe mesaj göndermek mobil hesabınızın premium hizmetle faturalandırılmasına neden olur.&lt;/b&gt;&lt;p&gt;Bu uygulamanın mesaj göndermesine izin vermek istiyor musunuz?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Mesajı gönder"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Gönderme"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Kötü amaçlı uygulamayı bildir"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kart çıkarıldı"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Geçerli bir SIM kart yerleştirilmiş olarak yeniden başlatana kadar mobil ağ kullanılamayacak."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tamamlandı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 8131fd7..0fe2afe 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Дозволяє програмі отримувати дані про внутрішній стан системи. Шкідливі програми можуть отримувати значну кількість особистої та конфіденційної інформації, яка для них не призначена."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"отримувати вміст екрана"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дозволяє програмі отримувати вміст активного вікна. Шкідливі програми можуть отримувати весь вміст вікна та вивчати весь його текст, окрім паролів."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"отримувати інформацію про вікна"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Дозволяє програмі отримувати інформацію про вікна від диспетчера вікон. Шкідливі програми можуть отримувати інформацію, яка призначена для внутрішнього користування системи."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"фільтрувати події"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Дозволяє програмі реєструвати вхідний фільтр, який фільтрує потік усіх подій користувача перед їх надсиланням. Шкідливі програми можуть контролювати інтерфейс системи без втручання користувача."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частк. заверш. роб."</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Переводить диспетчер дій у стан завершення роботи. Не виконує повне завершення роботи."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копіюв. URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Вибрати текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Вибір тексту"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"додати в словник"</string>
-    <string name="deleteText" msgid="7070985395199629156">"видалити"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Додати в словник"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Видалити"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод введення"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Дії з текстом"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Закінчується пам’ять"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"Програма &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; надсилає велику кількість SMS-повідомлень. Дозволити цій програмі й надалі надсилати повідомлення?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Дозволити"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Відмовити"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Надіслати SMS на короткий код?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Надіслати спеціальне SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Програма &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; хоче надіслати текстове повідомлення на адресу &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, яка є коротким кодом SMS.&lt;p&gt;&lt;b&gt;Якщо надсилати текстові повідомлення на певні короткі коди, з вашого мобільного рахунку буде стягнено плату за спеціальні послуги.&lt;/b&gt;&lt;p&gt;Дозволити цій програмі надіслати повідомлення?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Програма &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; хоче надіслати текстове повідомлення на адресу &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, яка є коротким кодом спеціальних SMS.&lt;p&gt;&lt;b&gt;Якщо надіслати повідомлення на цю адресу, з вашого мобільного рахунку буде стягнено плату за спеціальні послуги.&lt;/b&gt;&lt;p&gt;Дозволити цій програмі надіслати повідомлення?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Надіслати повідомлення"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не надсилати"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Повідом. про шкідливу програму"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карту вилучено"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мобільна мережа буде недоступна, поки ви не здійсните перезапуск, вставивши дійсну SIM-карту."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index d9de025..5a4e236 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Cho phép ứng dụng truy xuất trạng thái nội bộ của hệ thống. Ứng dụng độc hại có thể truy xuất nhiều loại thông tin riêng tư và bảo mật khác nhau mà thông thường chúng không bao giờ cần."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"truy xuất nội dung màn hình"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Cho phép ứng dụng truy xuất nội dung của cửa sổ hiện hành. Ứng dụng độc hại có thể truy xuất toàn bộ nội dung của cửa sổ cũng như xem xét toàn bộ văn bản của cửa sổ ngoại trừ mật khẩu."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"truy xuất thông tin cửa sổ"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Cho phép ứng dụng truy xuất thông tin về các cửa sổ từ trình quản lý cửa sổ. Các ứng dụng độc hại có thể truy xuất thông tin được dành để sử dụng trong hệ thống nội bộ."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"lọc sự kiện"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Cho phép ứng dụng đăng ký bộ lọc dữ liệu nhập để lọc luồng tất cả các sự kiện người dùng trước khi chúng được gửi đi. Ứng dụng độc hại có thể kiểm soát Giao diện người dùng hệ thống mà không cần sự can thiệp của người dùng."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"tắt từng phần"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Đặt trình quản lý hoạt động sang trạng thái tắt. Không thực hiện tắt hoàn toàn."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Sao chép URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Chọn văn bản"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Lựa chọn văn bản"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"thêm vào từ điển"</string>
-    <string name="deleteText" msgid="7070985395199629156">"xóa"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Thêm vào từ điển"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Xóa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Phương thức nhập"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tác vụ văn bản"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Sắp hết dung lượng lưu trữ"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; đang gửi rất nhiều tin nhắn SMS. Bạn có muốn cho phép ứng dụng này tiếp tục gửi tin nhắn không?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Cho phép"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Từ chối"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Gửi SMS cho mã ngắn?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Gửi tin nhắn SMS trả phí?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; muốn gửi tin nhắn văn bản cho &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, dường như là một mã ngắn SMS.&lt;p&gt;Việc gửi tin nhắn văn bản cho một số mã ngắn có thể khiến cho tài khoản di động của bạn bị lập hóa đơn cho dịch vụ trả phí.&lt;p&gt;Bạn có muốn cho phép ứng dụng này gửi tin nhắn không?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; muốn gửi tin nhắn văn bản cho &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, là một mã ngắn SMS trả phí.&lt;p&gt;&lt;b&gt;Gửi tin nhắn tới địa chỉ này sẽ khiến cho tài khoản di động của bạn bị lập hóa đơn cho dịch vụ trả phí.&lt;/b&gt;&lt;p&gt;Bạn có muốn cho phép ứng dụng này gửi tin nhắn không?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Gửi tin nhắn"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Không gửi"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Báo cáo ứng dụng độc hại"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Đã xóa thẻ SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mạng di động sẽ không khả dụng cho đến khi bạn khởi động lại với thẻ SIM hợp lệ được lắp."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Xong"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f2f9fde..2657d92 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"允许应用检索系统的内部状态。恶意应用可能会检索一般情况下绝不需要检索的多种私人信息和安全信息。"</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"检索屏幕内容"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允许应用检索活动窗口的内容。恶意应用可能会检索整个窗口的内容,并检查其中除密码以外的所有文字。"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"检索窗口信息"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允许应用通过窗口管理器检索窗口信息。恶意应用可能会检索供内部系统使用的信息。"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"过滤事件"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"允许应用注册输入过滤器,这类过滤器会在所有用户事件分派之前对用户事件流进行过滤。恶意应用可能会在没有用户干预的情况下控制系统用户界面。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"复制网址"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"选择文字"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"文字选择"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"添加到词典"</string>
-    <string name="deleteText" msgid="7070985395199629156">"删除"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"添加到词典"</string>
+    <string name="deleteText" msgid="6979668428458199034">"删除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"输入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字操作"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"存储空间不足"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;在发送大量短信。是否允许该应用继续发送短信?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"允许"</string>
     <string name="sms_control_no" msgid="625438561395534982">"拒绝"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"是否向短码发送短信?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"是否发送付费短信?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;想要向 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(这似乎是一个短信短码)发送短信。&lt;p&gt;向某些短码发送短信可能会导致您的移动帐户因使用付费服务而扣费。&lt;p&gt;是否允许该应用发送短信?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;想要向 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(这是一个付费短信短码)发送短信。&lt;p&gt;&lt;b&gt;向该地址发送短信会导致您的移动帐户因使用付费服务而扣费&lt;/b&gt;。&lt;p&gt;是否允许该应用发送短信?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"发送短信"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"不发送"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"举报恶意应用"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"已移除 SIM 卡"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"移动网络不可用。请插入有效的 SIM 卡并重新启动。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 8975871..8a8cb8e 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"允許應用程式擷取系統內部狀態。請注意,惡意應用程式可能利用此功能異常擷取各類私人資訊和安全性資訊。"</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"擷取螢幕內容"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允許應用程式擷取使用中的視窗內容。請注意,惡意應用程式可能利用此功能擷取完整視窗內容,並檢視密碼之外的所有文字。"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"擷取視窗資訊"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允許應用程式透過視窗管理程式擷取視窗的相關資訊。請注意,惡意應用程式可能藉此擷取僅限內部系統使用的資訊。"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有使用者活動的串流前先行篩選。請注意,惡意應用程式可能藉此擅自控制系統使用者介面。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"複製網址"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"選取文字"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"選取文字"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"新增至字典"</string>
-    <string name="deleteText" msgid="7070985395199629156">"刪除"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"加入字典"</string>
+    <string name="deleteText" msgid="6979668428458199034">"刪除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"輸入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字動作"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"儲存空間即將用盡"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;&lt;/b&gt;「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在傳送大量簡訊。您要允許這個應用程式繼續傳送簡訊嗎?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"允許"</string>
     <string name="sms_control_no" msgid="625438561395534982">"拒絕"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"傳送簡訊給短碼?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"傳送付費簡訊?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;&lt;/b&gt;「<xliff:g id="APP_NAME">%1$s</xliff:g>」想要傳送簡訊給簡訊短碼 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。&lt;p&gt;將簡訊傳送給對方之後,系統即會從您的行動帳戶收取付費服務的費用。&lt;p&gt;您要允許這個應用程式傳送簡訊嗎?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;&lt;/b&gt;「<xliff:g id="APP_NAME">%1$s</xliff:g>」想要傳送簡訊給付費簡訊短碼 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。&lt;p&gt;&lt;b&gt;將簡訊傳送給對方之後,系統即會從您的行動帳戶收取付費服務的費用。&lt;/b&gt;&lt;p&gt;您要允許這個應用程式傳送簡訊嗎?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"傳送簡訊"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"不要傳送"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"檢舉惡意應用程式"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM 卡已移除"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"您必須先插入有效的 SIM 卡再重新啟動手機,才能使用行動網路。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a2bc951..59cdab1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -243,6 +243,10 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Ivumela insiza ukuthi ithole kabusha ingaphakathi lesistimu. izinsiza ezinobungozi zingathola kabusha inqwaba yolwazi oluyimfihlo noluvikelekile ezingajwayele ukuthi ziludinge."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"letha okuqukethwe kwesikrini"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ivumela insiza ukuthi ithole okuqukethe kwi-Window. Izinsiza ezinobungozi zingathola kabush iwindi eliphelele bese ibheka konke okuqukethwe ngaphandle kwaaaphasiwedi."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"buyisa ulwazi lewindi"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana namawindi avela kumphathi wewindi. Izinhlelo zokusebenza zingabuyisa ulwazi olubhekiswe ukusetshenziselwa kohlelo lwangaphakathi."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"hlunga izehlakalo"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ivumela uhlelo lokusebenza ukubhalisa isihlungi sokufaka ukusakaza kwazo zonke izehlakalo zomsebenzisi ngaphambi kokuthunyelwa. Izinhlelo zokusebenza zingalawula i-UI yohlelo ngaphandle kokungena komsebenzisi."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ukuvala shaqa kwengxenye"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ibeka imeneja yomsebenzi kwisimo sokuvala shaqa. Ayenzi ukuvala shaqa okuphelele."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"gwema ukushintsha kohlelo lokusebenza"</string>
@@ -930,8 +934,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopisha i-URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Khetha umbhalo"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Inketho yombhalo"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"Faka esichazinimazwi"</string>
-    <string name="deleteText" msgid="7070985395199629156">"susa"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Engeza kwisichazamazwi"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Susa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Indlela yokufakwayo"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Izenzo zombhalo"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Isikhala sokulondoloza siyaphela"</string>
@@ -1033,6 +1037,13 @@
     <string name="sms_control_message" msgid="3867899169651496433">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithumela inombolo enkulu yemilayezo ye-SMS. Ufuna ukuvumela lolu hlelo lokusebenza ukuqhubeka ukuthumela imilayezo?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Vumela"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nqaba"</string>
+    <string name="sms_short_code_confirm_title" msgid="1666863092640877318">"Thumela i-SMS kukhodi emfushane?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Ukuthumela i-SMS ye-premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithanda ukuthumela umlayezo wombhalo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, okubonakala sengathi ikhodi ye-SMS emfushane.&lt;p&gt;Ukuthumela umlayezo wombhalo kungabangela i-akhawunti yeselula yakho ukuthi ikhokheliswe amasevisi e-premium.&lt;p&gt;Ufuna ukuvumela uhlelo lokusebenza ukuthumela umlayezo?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithanda ukuthumela umlayezo wombhalo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, okuyikhodi emfushane ye-SMS ye-premium.&lt;p&gt;&lt;b&gt;Ukuthumela umlayezo kule ndawo kuzobangela i-akhawunti yeselula yakho ukuthi ikhokheliswe amasevisi e-premium.&lt;/b&gt;&lt;p&gt;Ufuna ukuvumela lolu hlelo lokusebenza ukuthumela umlayezo?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Thumela umlayezo"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ungathumeli"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Bika uhlelo lokusebenza olungalungile"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Ikhadi le-SIM likhishiwe"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Inethiwekhi yeselula ngeke itholakale kuwena kuze kube uqala kabusha ufake ikhadi le-SIM elifanele."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwenziwe"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index b425ad7..8615476 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -242,8 +242,6 @@
        <item>@drawable/list_divider_holo_dark</item>
        <item>@drawable/list_divider_holo_light</item>
        <item>@drawable/list_divider_holo_light</item>
-       <item>@drawable/ic_lockscreen_chevron_left</item>
-       <item>@drawable/ic_lockscreen_chevron_right</item>
        <item>@drawable/ab_transparent_dark_holo</item>
        <item>@drawable/ab_stacked_transparent_dark_holo</item>
        <item>@drawable/ab_bottom_transparent_dark_holo</item>
@@ -400,11 +398,4 @@
         <item>@null</item>
     </array>
 
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index aa8b643..6386bcb 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -275,6 +275,11 @@
         <!-- The preferred item height for dropdown lists. -->
         <attr name="dropdownListPreferredItemHeight" format="dimension" />
 
+        <!-- The preferred padding along the start edge of list items. -->
+        <attr name="listPreferredItemPaddingStart" format="dimension" />
+        <!-- The preferred padding along the end edge of list items. -->
+        <attr name="listPreferredItemPaddingEnd" format="dimension" />
+
         <!-- ============= -->
         <!-- Window styles -->
         <!-- ============= -->
@@ -2154,40 +2159,6 @@
             <enum name="no" value="2" />
         </attr>
 
-        <!-- @hide Controls whether this view can take accessibility focus. -->
-        <attr name="accessibilityFocusable" format="integer">
-            <!-- The system determines whether the view can take accessibility focus - default
-                 (recommended).
-                 <p>
-                 Such a view is consideted by the focus search if it is:
-                 <ul>
-                 <li>
-                 Important for accessibility and actionable (clickable, long clickable, focusable)
-                 </li>
-                 <li>
-                 Important for accessibility, not actionable (clickable, long clickable, focusable),
-                 and does not have an actionable predecessor.
-                 </li>
-                 </ul>
-                 An accessibility srvice can request putting accessibility focus on such a view.
-                 </p> -->
-            <enum name="auto" value="0" />
-            <!-- The view can take accessibility focus.
-                 <p>
-                 A view that can take accessibility focus is always considered during focus
-                 search and an accessibility service can request putting accessibility focus
-                 on it.
-                 </p> -->
-            <enum name="yes" value="1" />
-            <!-- The view can not take accessibility focus.
-                 <p>
-                 A view that can not take accessibility focus is never considered during focus
-                 search and an accessibility service can not request putting accessibility focus
-                 on it.
-                 </p> -->
-            <enum name="no" value="2" />
-        </attr>
-
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -3668,6 +3639,24 @@
         <!-- If set to true, the parent will be used as the anchor when the anchor cannot be
              be found for layout_toLeftOf, layout_toRightOf, etc. -->
         <attr name="layout_alignWithParentIfMissing" format="boolean" />
+        <!-- Positions the end edge of this view to the start of the given anchor view ID.
+             Accommodates end margin of this view and start margin of anchor view. -->
+        <attr name="layout_toStartOf" format="reference" />
+        <!-- Positions the start edge of this view to the end of the given anchor view ID.
+             Accommodates start margin of this view and end margin of anchor view. -->
+        <attr name="layout_toEndOf" format="reference" />
+        <!-- Makes the start edge of this view match the start edge of the given anchor view ID.
+            Accommodates start margin. -->
+        <attr name="layout_alignStart" format="reference" />
+        <!-- Makes the end edge of this view match the end edge of the given anchor view ID.
+            Accommodates end margin. -->
+        <attr name="layout_alignEnd" format="reference" />
+        <!-- If true, makes the start edge of this view match the start edge of the parent.
+            Accommodates start margin. -->
+        <attr name="layout_alignParentStart" format="boolean" />
+        <!-- If true, makes the end edge of this view match the end edge of the parent.
+            Accommodates end margin. -->
+        <attr name="layout_alignParentEnd" format="boolean" />
     </declare-styleable>
     <declare-styleable name="VerticalSlider_Layout">
         <attr name="layout_scale" format="float" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a2e15e6..39129e5 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -65,6 +65,11 @@
          master volume stream and nothing else . -->
     <bool name="config_useMasterVolume">false</bool>
 
+    <!-- Flag indicating that the media framework should support playing of sounds on volume
+         key usage.  This adds noticeable additional overhead to volume key processing, so
+         is disableable for products for which it is irrelevant. -->
+    <bool name="config_useVolumeKeySounds">true</bool>
+
     <!-- Array of integer pairs controlling the rate at which the master volume changes
          in response to volume up and down key events.
          The first integer of each pair is compared against the current master volume
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 40768a0..b9b8a1b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -261,6 +261,7 @@
   <java-symbol type="bool" name="skip_restoring_network_selection" />
   <java-symbol type="bool" name="split_action_bar_is_narrow" />
   <java-symbol type="bool" name="config_useMasterVolume" />
+  <java-symbol type="bool" name="config_useVolumeKeySounds" />
   <java-symbol type="bool" name="config_enableWallpaperService" />
   <java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
   <java-symbol type="bool" name="config_enableScreenshotChord" />
@@ -923,8 +924,6 @@
   <java-symbol type="array" name="config_cdma_dun_supported_types" />
 
   <java-symbol type="drawable" name="default_wallpaper" />
-  <java-symbol type="drawable" name="ic_suggestions_add" />
-  <java-symbol type="drawable" name="ic_suggestions_delete" />
   <java-symbol type="drawable" name="indicator_input_error" />
   <java-symbol type="drawable" name="overscroll_edge" />
   <java-symbol type="drawable" name="overscroll_glow" />
@@ -3660,4 +3659,25 @@
   <public type="style" name="Widget.DeviceDefault.MediaRouteButton" id="0x010301d7" />
   <public type="style" name="Widget.DeviceDefault.Light.MediaRouteButton" id="0x010301d8" />
 
+<!-- ===============================================================
+     Resources added in version 17 of the platform (Jelly Bean MRx?)
+     =============================================================== -->
+  <eat-comment />
+  <public type="attr" name="supportsRtl" />
+  <public type="attr" name="textDirection" />
+  <public type="attr" name="textAlignment" />
+  <public type="attr" name="layoutDirection" />
+  <public type="attr" name="paddingStart"/>
+  <public type="attr" name="paddingEnd"/>
+  <public type="attr" name="layout_marginStart"/>
+  <public type="attr" name="layout_marginEnd"/>
+  <public type="attr" name="layout_toStartOf" />
+  <public type="attr" name="layout_toEndOf" />
+  <public type="attr" name="layout_alignStart" />
+  <public type="attr" name="layout_alignEnd" />
+  <public type="attr" name="layout_alignParentStart" />
+  <public type="attr" name="layout_alignParentEnd" />
+  <public type="attr" name="listPreferredItemPaddingStart" />
+  <public type="attr" name="listPreferredItemPaddingEnd" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3582768..a39d98d 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -630,6 +630,20 @@
         the entire window content and examine all its text except passwords.</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_retrieve_window_info">retrieve window info</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_retrieve_window_info">Allows an application to retrieve
+         information about the the windows from the window manager. Malicious apps may
+         retrieve information that is intended for internal system usage.</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_filter_events">filter events</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_filter_events">Allows an application to register an input filter
+        which filters the stream of all user events before they are dispatched. Malicious app
+        may control the system UI whtout user intervention.</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_shutdown">partial shutdown</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_shutdown">Puts the activity manager into a shutdown
@@ -2693,10 +2707,10 @@
     <string name="textSelectionCABTitle">Text selection</string>
 
     <!-- Option to add the current misspelled word to the user dictionary. [CHAR LIMIT=25] -->
-    <string name="addToDictionary">add to dictionary</string>
+    <string name="addToDictionary">Add to dictionary</string>
 
     <!-- Option to delete the highlighted part of the text from the suggestion popup. [CHAR LIMIT=25] -->
-    <string name="deleteText">delete</string>
+    <string name="deleteText">Delete</string>
 
     <!-- EditText context menu -->
     <string name="inputMethod">Input method</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e4fc26b..c490a2f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -339,21 +339,18 @@
         <item name="android:clickable">true</item>
         <item name="android:textAppearance">?android:attr/textAppearance</item>
         <item name="android:textColor">?android:attr/textColorPrimaryDisableOnly</item>
-        <item name="android:gravity">center_vertical|left</item>
+        <item name="android:gravity">center_vertical|start</item>
     </style>
 
     <style name="Widget.CompoundButton.CheckBox">
-        <item name="android:background">@android:drawable/btn_check_label_background</item>
         <item name="android:button">?android:attr/listChoiceIndicatorMultiple</item>
     </style>
 
     <style name="Widget.CompoundButton.RadioButton">
-        <item name="android:background">@android:drawable/btn_radio_label_background</item>
         <item name="android:button">?android:attr/listChoiceIndicatorSingle</item>
     </style>
 
     <style name="Widget.CompoundButton.Star">
-        <item name="android:background">@android:drawable/btn_star_label_background</item>
         <item name="android:button">@android:drawable/btn_star</item>
     </style>
 
@@ -476,7 +473,7 @@
         <item name="android:textColor">?textColorSecondary</item>
         <item name="android:textSize">14sp</item>
         <item name="android:gravity">center_vertical</item>
-        <item name="android:paddingLeft">8dip</item>
+        <item name="android:paddingStart">8dip</item>
     </style>
 
     <style name="Widget.TextView.ListSeparator.White">
@@ -587,8 +584,8 @@
 
     <style name="Widget.DropDownItem">
         <item name="android:textAppearance">@style/TextAppearance.Widget.DropDownItem</item>
-        <item name="android:paddingLeft">@dimen/dropdownitem_text_padding_left</item>
-        <item name="android:paddingRight">@dimen/dropdownitem_text_padding_right</item>
+        <item name="android:paddingStart">@dimen/dropdownitem_text_padding_left</item>
+        <item name="android:paddingEnd">@dimen/dropdownitem_text_padding_right</item>
         <item name="android:gravity">center_vertical</item>
     </style>
     
@@ -928,8 +925,8 @@
     </style>
 
     <style name="PreferenceFragment">
-        <item name="android:paddingLeft">0dp</item>
-        <item name="android:paddingRight">0dp</item>
+        <item name="android:paddingStart">0dp</item>
+        <item name="android:paddingEnd">0dp</item>
     </style>
 
     <style name="Preference.Information">
@@ -983,8 +980,8 @@
     </style>
 
     <style name="PreferenceFragment.Holo">
-        <item name="android:paddingLeft">@dimen/preference_fragment_padding_side</item>
-        <item name="android:paddingRight">@dimen/preference_fragment_padding_side</item>
+        <item name="android:paddingStart">@dimen/preference_fragment_padding_side</item>
+        <item name="android:paddingEnd">@dimen/preference_fragment_padding_side</item>
     </style>
 
     <style name="Preference.Holo.Information">
@@ -1040,8 +1037,8 @@
     <!-- The attributes are overridden here because the x-large or large resources may have
          changed the margins and background in the parent PreferencePanel style. -->
     <style name="PreferencePanel.Dialog">
-        <item name="android:layout_marginLeft">0dip</item>
-        <item name="android:layout_marginRight">0dip</item>
+        <item name="android:layout_marginStart">0dip</item>
+        <item name="android:layout_marginEnd">0dip</item>
         <item name="android:layout_marginTop">0dip</item>
         <item name="android:layout_marginBottom">0dip</item>
         <item name="android:background">@null</item>
@@ -1082,8 +1079,8 @@
 
     <style name="ZoomControls">
         <item name="android:gravity">bottom</item>
-        <item name="android:paddingLeft">15dip</item>
-        <item name="android:paddingRight">15dip</item>
+        <item name="android:paddingStart">15dip</item>
+        <item name="android:paddingEnd">15dip</item>
     </style>
     
     <!-- Style you can use with a container (typically a horizontal
@@ -1091,8 +1088,8 @@
          spacing. @hide -->
     <style name="ButtonBar">
         <item name="android:paddingTop">5dip</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
         <item name="android:paddingBottom">1dip</item>
         <item name="android:background">@android:drawable/bottom_bar</item>
     </style>
@@ -1128,9 +1125,9 @@
         <item name="android:displayOptions">useLogo|showHome|showTitle</item>
         <item name="android:divider">@android:drawable/action_bar_divider</item>
         <item name="android:height">?android:attr/actionBarSize</item>
-        <item name="android:paddingLeft">0dip</item>
+        <item name="android:paddingStart">0dip</item>
         <item name="android:paddingTop">0dip</item>
-        <item name="android:paddingRight">0dip</item>
+        <item name="android:paddingEnd">0dip</item>
         <item name="android:paddingBottom">0dip</item>
         <item name="android:titleTextStyle">@android:style/TextAppearance.Widget.ActionBar.Title</item>
         <item name="android:subtitleTextStyle">@android:style/TextAppearance.Widget.ActionBar.Subtitle</item>
@@ -1166,8 +1163,8 @@
 
     <style name="Widget.ActionButton">
         <item name="android:background">?android:attr/actionBarItemBackground</item>
-        <item name="android:paddingLeft">12dip</item>
-        <item name="android:paddingRight">12dip</item>
+        <item name="android:paddingStart">12dip</item>
+        <item name="android:paddingEnd">12dip</item>
         <item name="android:minWidth">@android:dimen/action_button_min_width</item>
         <item name="android:minHeight">?android:attr/actionBarSize</item>
         <item name="android:gravity">center</item>
@@ -1185,8 +1182,8 @@
     <style name="Widget.ActionBar.TabView" parent="Widget">
         <item name="android:gravity">center_horizontal</item>
         <item name="android:background">@drawable/minitab_lt</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="Widget.ActionBar.TabBar" parent="Widget">
@@ -1533,8 +1530,8 @@
 
     <style name="Widget.Holo.Button.Borderless">
         <item name="android:background">?android:attr/selectableItemBackground</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="Widget.Holo.Button.Borderless.Small">
@@ -1564,8 +1561,8 @@
 
     <style name="Holo.ButtonBar" parent="ButtonBar">
         <item name="android:paddingTop">0dip</item>
-        <item name="android:paddingLeft">0dip</item>
-        <item name="android:paddingRight">0dip</item>
+        <item name="android:paddingStart">0dip</item>
+        <item name="android:paddingEnd">0dip</item>
         <item name="android:paddingBottom">0dip</item>
         <item name="divider">?android:attr/dividerVertical</item>
         <item name="showDividers">middle</item>
@@ -1732,8 +1729,8 @@
         <item name="android:thumb">@android:drawable/scrubber_control_selector_holo</item>
         <item name="android:thumbOffset">16dip</item>
         <item name="android:focusable">true</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
+        <item name="android:paddingStart">16dip</item>
+        <item name="android:paddingEnd">16dip</item>
     </style>
 
     <style name="Widget.Holo.RatingBar" parent="Widget.RatingBar">
@@ -1772,7 +1769,7 @@
         <item name="android:dropDownHorizontalOffset">0dip</item>
         <item name="android:dropDownWidth">wrap_content</item>
         <item name="android:popupPromptView">@android:layout/simple_dropdown_hint</item>
-        <item name="android:gravity">left|center_vertical</item>
+        <item name="android:gravity">start|center_vertical</item>
         <item name="android:disableChildrenWhenDisabled">true</item>
     </style>
 
@@ -1817,8 +1814,8 @@
 
     <style name="Widget.Holo.DropDownItem" parent="Widget.DropDownItem">
         <item name="android:textAppearance">@style/TextAppearance.Holo.Widget.DropDownItem</item>
-        <item name="android:paddingLeft">8dp</item>
-        <item name="android:paddingRight">8dp</item>
+        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingEnd">8dp</item>
     </style>
 
     <style name="Widget.Holo.DropDownItem.Spinner">
@@ -1826,8 +1823,8 @@
 
     <style name="Widget.Holo.TextView.SpinnerItem" parent="Widget.TextView.SpinnerItem">
         <item name="android:textAppearance">@style/TextAppearance.Holo.Widget.TextView.SpinnerItem</item>
-        <item name="android:paddingLeft">8dp</item>
-        <item name="android:paddingRight">8dp</item>
+        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingEnd">8dp</item>
     </style>
 
     <style name="Widget.Holo.KeyboardView" parent="Widget.KeyboardView">
@@ -1872,8 +1869,8 @@
     <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
         <item name="android:minWidth">@android:dimen/action_button_min_width</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">12dip</item>
-        <item name="android:paddingRight">12dip</item>
+        <item name="android:paddingStart">12dip</item>
+        <item name="android:paddingEnd">12dip</item>
         <item name="android:scaleType">center</item>
         <item name="android:maxLines">2</item>
     </style>
@@ -1889,8 +1886,8 @@
 
     <style name="Widget.Holo.ActionBar.TabView" parent="Widget.ActionBar.TabView">
         <item name="android:background">@drawable/tab_indicator_ab_holo</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
+        <item name="android:paddingStart">16dip</item>
+        <item name="android:paddingEnd">16dip</item>
     </style>
 
     <style name="Widget.Holo.ActionBar.TabBar" parent="Widget.ActionBar.TabBar">
@@ -1970,8 +1967,8 @@
 
     <style name="Widget.Holo.Light.Button.Borderless">
         <item name="android:background">?android:attr/selectableItemBackground</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="Widget.Holo.Light.Button.Borderless.Small">
@@ -2419,10 +2416,10 @@
         <item name="android:layout_width">200dip</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginTop">8dip</item>
-        <item name="android:layout_marginLeft">16dip</item>
-        <item name="android:layout_marginRight">16dip</item>
+        <item name="android:layout_marginStart">16dip</item>
+        <item name="android:layout_marginEnd">16dip</item>
         <item name="android:orientation">vertical</item>
-        <item name="android:gravity">left</item>
+        <item name="android:gravity">start</item>
     </style>
 
     <!-- @hide -->
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 2f18944..9c12263 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -128,6 +128,8 @@
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceLarge</item>
         <item name="listPreferredItemPaddingLeft">6dip</item>
         <item name="listPreferredItemPaddingRight">6dip</item>
+        <item name="listPreferredItemPaddingStart">6dip</item>
+        <item name="listPreferredItemPaddingEnd">6dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -637,6 +639,8 @@
 
         <item name="listPreferredItemPaddingLeft">10dip</item>
         <item name="listPreferredItemPaddingRight">10dip</item>
+        <item name="listPreferredItemPaddingStart">10dip</item>
+        <item name="listPreferredItemPaddingEnd">10dip</item>
     </style>
 
     <!-- Variant of {@link Theme_Dialog} that does not include a frame (or background).
@@ -962,6 +966,8 @@
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
         <item name="listPreferredItemPaddingRight">8dip</item>
+        <item name="listPreferredItemPaddingStart">8dip</item>
+        <item name="listPreferredItemPaddingEnd">8dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -1267,6 +1273,8 @@
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
         <item name="listPreferredItemPaddingRight">8dip</item>
+        <item name="listPreferredItemPaddingStart">8dip</item>
+        <item name="listPreferredItemPaddingEnd">8dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -1573,6 +1581,8 @@
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
     </style>
 
     <!-- Variant of Theme.Holo.Dialog that has a nice minimum width for
@@ -1681,6 +1691,8 @@
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
     </style>
 
     <!-- Variant of Theme.Holo.Light.Dialog that has a nice minimum width for
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 30312b3..7af3b9c 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -18,37 +18,44 @@
 -->
 
 <device name="Android">
-  <!-- All values are in mAh except as noted -->
+  <!-- Most values are the incremental current used by a feature,
+       in mA (measured at nominal voltage).
+       The default values are deliberately incorrect dummy values.
+       OEM's must measure and provide actual values before
+       shipping a device.
+       Example real-world values are given in comments, but they
+       are totally dependent on the platform and can vary
+       significantly, so should be measured on the shipping platform
+       with a power meter. -->
   <item name="none">0</item>
-  <item name="screen.on">0.1</item>
-  <item name="bluetooth.active">0.1</item>
-  <item name="bluetooth.on">0.1</item>
-  <item name="screen.full">0.1</item>
-  <item name="wifi.on">0.1</item>
-  <item name="wifi.active">0.1</item>
-  <item name="wifi.scan">0.1</item>
-  <item name="dsp.audio">0.1</item>
-  <item name="dsp.video">0.1</item>
-  <item name="radio.active">1</item>
-  <!-- The current consumed by the radio when it is scanning for a signal -->
-  <item name="radio.scanning">0.5</item>
-  <item name="gps.on">1</item>
+  <item name="screen.on">0.1</item>  <!-- ~200mA -->
+  <item name="screen.full">0.1</item>  <!-- ~300mA -->
+  <item name="bluetooth.active">0.1</item> <!-- Bluetooth data transfer, ~10mA -->
+  <item name="bluetooth.on">0.1</item>  <!-- Bluetooth on & connectable, but not connected, ~0.1mA -->
+  <item name="wifi.on">0.1</item>  <!-- ~3mA -->
+  <item name="wifi.active">0.1</item>  <!-- WIFI data transfer, ~200mA -->
+  <item name="wifi.scan">0.1</item>  <!-- WIFI network scanning, ~100mA -->
+  <item name="dsp.audio">0.1</item> <!-- ~10mA -->
+  <item name="dsp.video">0.1</item> <!-- ~50mA -->
+  <item name="radio.active">0.1</item> <!-- ~200mA -->
+  <item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA -->
+  <item name="gps.on">0.1</item> <!-- ~50mA -->
   <!-- Current consumed by the radio at different signal strengths, when paging -->
   <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
-      <value>0.2</value>
-      <value>0.1</value>
+      <value>0.2</value> <!-- ~2mA -->
+      <value>0.1</value> <!-- ~1mA -->
   </array>
   <!-- Different CPU speeds as reported in
        /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state -->
   <array name="cpu.speeds">
       <value>400000</value> <!-- 400 MHz CPU speed -->
   </array>
-  <!-- Power consumption when CPU is idle -->
+  <!-- Current when CPU is idle -->
   <item name="cpu.idle">0.1</item>
-  <!-- Power consumption at different speeds -->
+  <!-- Current at each CPU speed, as per 'cpu.speeds' -->
   <array name="cpu.active">
-      <value>0.2</value>
+      <value>0.1</value>  <!-- ~100mA -->
   </array>
-  <!-- This is the battery capacity in mAh -->
+  <!-- This is the battery capacity in mAh (measured at nominal voltage) -->
   <item name="battery.capacity">1000</item>
 </device>
diff --git a/core/tests/coretests/apks/version/Android.mk b/core/tests/coretests/apks/version/Android.mk
new file mode 100644
index 0000000..3635a58
--- /dev/null
+++ b/core/tests/coretests/apks/version/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_1
+LOCAL_AAPT_FLAGS := --version-code 1 --version-name 1.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_2
+LOCAL_AAPT_FLAGS := --version-code 2 --version-name 2.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_3
+LOCAL_AAPT_FLAGS := --version-code 3 --version-name 3.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_1_diff
+LOCAL_AAPT_FLAGS := --version-code 1 --version-name 1.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test_diff
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_2_diff
+LOCAL_AAPT_FLAGS := --version-code 2 --version-name 2.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test_diff
+include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/version/AndroidManifest.xml b/core/tests/coretests/apks/version/AndroidManifest.xml
new file mode 100644
index 0000000..c35ae63
--- /dev/null
+++ b/core/tests/coretests/apks/version/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.version_test">
+
+    <!-- Which permission it uses is not important as long as it's a system-only
+         permission -->
+    <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
+
+    <!-- Which permission it uses is not important as long as it's a normal
+         permission -->
+    <uses-permission android:name="android.permission.VIBRATE" />
+
+    <application android:hasCode="false"/>
+</manifest>
diff --git a/core/tests/coretests/apks/version/res/values/strings.xml b/core/tests/coretests/apks/version/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/version/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/version/src/com/android/frameworks/coretests/version_test/NullProvider.java b/core/tests/coretests/apks/version/src/com/android/frameworks/coretests/version_test/NullProvider.java
new file mode 100644
index 0000000..f5742f0
--- /dev/null
+++ b/core/tests/coretests/apks/version/src/com/android/frameworks/coretests/version_test/NullProvider.java
@@ -0,0 +1,39 @@
+package com.android.frameworks.coretests.version_test;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class NullProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "text/plain";
+    }
+}
diff --git a/core/tests/coretests/certs/README b/core/tests/coretests/certs/README
new file mode 100644
index 0000000..00917a1
--- /dev/null
+++ b/core/tests/coretests/certs/README
@@ -0,0 +1,4 @@
+Generate with:
+
+development/tools/make_key unit_test         '/CN=unit_test'
+development/tools/make_key unit_test_diff    '/CN=unit_test_diff'
diff --git a/core/tests/coretests/certs/unit_test.pk8 b/core/tests/coretests/certs/unit_test.pk8
new file mode 100644
index 0000000..f935e3e
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/unit_test.x509.pem b/core/tests/coretests/certs/unit_test.x509.pem
new file mode 100644
index 0000000..21c4beb
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIJAJnvhSUT7hwkMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
+BAMUCXVuaXRfdGVzdDAeFw0xMjA1MDgwNTUwMDJaFw0zOTA5MjQwNTUwMDJaMBQx
+EjAQBgNVBAMUCXVuaXRfdGVzdDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
+ggEBAOm2mt+vcNjDqTx1SVMj0tQcAJU49zao6rKigV+D7QdLfVOYbzdlJjL7CVZQ
+7+Tjq/mXHmNyUi7eI/eTgzZOXEjuf1moFoFvqxFeIHgR1iWAkODJ5FTGZEDiK4gY
+amfS7LVwqsr1ExE6XfBUb5n/34V/Twr6suSRVjcS3OI5X3Yh/Ip/I2SNCJ6Kz5EX
+RVk0T+I0zhIHX8+57Dp+0j3Cq0hb7ROylIbxrKzv1cpxt3FUrZXpLspalYvUoYLU
+Jr3XA9vfbSf2NPqGz8VeUxvqoWcMhyMEuswwQF1YPU9HCIKhC76Xd8O5hIKy7jlo
+ZNSiKmKySyy8IJB4w+Hxd70h6TMCAQOjdTBzMB0GA1UdDgQWBBSDs4X8MYwKBmiw
+f+RqeLc8R8XaoTBEBgNVHSMEPTA7gBSDs4X8MYwKBmiwf+RqeLc8R8XaoaEYpBYw
+FDESMBAGA1UEAxQJdW5pdF90ZXN0ggkAme+FJRPuHCQwDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQUFAAOCAQEAmRIybRohluR/zcrwRK5TpJIfArSNBdWLbfEyo+ug
+mzMLq/RUHXXJSmqXaX/4tcW/LfjiCZjKmoauGSe9u979lX8nTKLBfeRWQpNUgwux
+pBBt2Ein14IP7rZI34bB3iN06KTTBfpK60XZR23n9gkWClmMuTSd8scX/XoYXfeW
+B0ePwQAMk1S1Ge5wbQCSJOCP5hTKzWio2S2rfw5pXa+ppHwXe0SWXtQHvMDu5WVy
+Cgwqu4yxrneHYGV3mphtHXdtCAgfh4L+/4ooHwzBfxVaDhyZ1UvoEntczEi/VEV2
+liP8IbwSp1x8Mdg8TIVJrDjvAoR6j8ie8i3IHNRzZLNJ0A==
+-----END CERTIFICATE-----
diff --git a/core/tests/coretests/certs/unit_test_diff.pk8 b/core/tests/coretests/certs/unit_test_diff.pk8
new file mode 100644
index 0000000..a85ec86
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test_diff.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/unit_test_diff.x509.pem b/core/tests/coretests/certs/unit_test_diff.x509.pem
new file mode 100644
index 0000000..e3e2197
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test_diff.x509.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLTCCAhWgAwIBAgIJAOZy2AGEfSxzMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
+BAMUDnVuaXRfdGVzdF9kaWZmMB4XDTEyMDUwODE5MjYwN1oXDTM5MDkyNDE5MjYw
+N1owGTEXMBUGA1UEAxQOdW5pdF90ZXN0X2RpZmYwggEgMA0GCSqGSIb3DQEBAQUA
+A4IBDQAwggEIAoIBAQDKuDr+3vZZrjJ2AeTDFZJjeQdFrwRQJ1BOBM5aot/uTCfX
+fe/CAm6Kn1rDtx+/srlLEqmjZDzzKYSpU7Vr0rOsTCTjWgis1/6jVydJgrsL6nXF
+oz8swqTa+IYpa4gjs08EEqfjbbGTtSfVi6jziw/Nebtl5XRBoREpV8cTJk+DZH/B
+8c0Ns8XpSawpFUDH9UXoEzNdje033HpTROWN7gbX9nA3x0YXdUnb8I0VcVf16m+3
+Tk07UkE/f7geOZ4CDF/a9dri9z5KWUlODOw7hlQG658N6gILmTc+5Vrree5eBLXo
+qeIyg2w0pZZLLATomVCVUm9CaGna+cUai3Hfb+bFAgEDo3oweDAdBgNVHQ4EFgQU
+xqP+zV47zj1Dsup1FU+PG1PBFZ4wSQYDVR0jBEIwQIAUxqP+zV47zj1Dsup1FU+P
+G1PBFZ6hHaQbMBkxFzAVBgNVBAMUDnVuaXRfdGVzdF9kaWZmggkA5nLYAYR9LHMw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAg5rZis/BVK8EYhdr8F6p
+yG7qYbHyYtswmGGu9MPcNKR9eclNd1VQktIEXoIqCq7DhHn0LWgedh4WHfCtbHmI
+iPi9HUjMBzLiUUsuRloPPe1DykFZJY3EUYH9JI0p+J+18grGakrlPKqbF6ymVN9w
+iaznMgf0qSpyIMFLgltLkiXPJUByTfADQBDsQe7njQlG4A+wSHTUN7XY32IIlQJ1
+lvmjBywZk4eJSv5qlefC2n/Zc4dl6jsiqhmx2aviO6fmuIsf4UprCRHlHOiNSmdL
+M2ggtqpnzoOVSZlsXvYITmnsWNxiavz1DvIbnwglngmaqeaB/0qepdRKH1BJkW8q
+9w==
+-----END CERTIFICATE-----
diff --git a/core/tests/coretests/src/android/app/InstrumentationTest.java b/core/tests/coretests/src/android/app/InstrumentationTest.java
new file mode 100644
index 0000000..ee3834c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/InstrumentationTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestCase;
+
+public class InstrumentationTest extends InstrumentationTestCase {
+
+    /**
+     * Simple stress test for {@link Instrumentation#sendStatus(int, android.os.Bundle)}, to
+     * ensure it can handle many rapid calls without failing.
+     */
+    public void testSendStatus() {
+        for (int i = 0; i < 10000; i++) {
+            Bundle bundle = new Bundle();
+            bundle.putInt("iterations", i);
+            getInstrumentation().sendStatus(-1, bundle);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/app/SearchablesTest.java b/core/tests/coretests/src/android/app/SearchablesTest.java
index 6cb31d4..4d3b144 100644
--- a/core/tests/coretests/src/android/app/SearchablesTest.java
+++ b/core/tests/coretests/src/android/app/SearchablesTest.java
@@ -71,7 +71,7 @@
      */
     public void testNonSearchable() {
         // test basic array & hashmap
-        Searchables searchables = new Searchables(mContext);
+        Searchables searchables = new Searchables(mContext, 0);
         searchables.buildSearchableList();
 
         // confirm that we return null for non-searchy activities
@@ -103,7 +103,7 @@
 
         // build item list with real-world source data
         mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
-        Searchables searchables = new Searchables(mockContext);
+        Searchables searchables = new Searchables(mockContext, 0);
         searchables.buildSearchableList();
         // tests with "real" searchables (deprecate, this should be a unit test)
         ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList();
@@ -122,7 +122,7 @@
         MyMockContext mockContext = new MyMockContext(mContext, mockPM);
 
         mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
-        Searchables searchables = new Searchables(mockContext);
+        Searchables searchables = new Searchables(mockContext, 0);
         searchables.buildSearchableList();
         ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList();
         assertNotNull(searchablesList);
diff --git a/core/tests/coretests/src/android/util/ListItemFactory.java b/core/tests/coretests/src/android/util/ListItemFactory.java
index e8a498d..3f48dcc 100644
--- a/core/tests/coretests/src/android/util/ListItemFactory.java
+++ b/core/tests/coretests/src/android/util/ListItemFactory.java
@@ -247,7 +247,7 @@
         TextView t1 = new TextView(context);
         t1.setHeight(desiredHeight);
         t1.setText(text);
-        t1.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        t1.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
         final ViewGroup.LayoutParams lp1 = new LinearLayout.LayoutParams(
                 0,
                 ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
diff --git a/core/tests/coretests/src/android/util/TimeUtilsTest.java b/core/tests/coretests/src/android/util/TimeUtilsTest.java
index 8d9f8e5..74c8e04 100644
--- a/core/tests/coretests/src/android/util/TimeUtilsTest.java
+++ b/core/tests/coretests/src/android/util/TimeUtilsTest.java
@@ -18,8 +18,6 @@
 
 import junit.framework.TestCase;
 
-import android.util.TimeUtils;
-
 import java.util.Calendar;
 import java.util.TimeZone;
 
@@ -442,6 +440,13 @@
         assertFormatDuration("+10s24ms", 10024);
     }
 
+    public void testFormatHugeDuration() {
+        //assertFormatDuration("+15542d1h11m11s555ms", 1342833071555L);
+        // TODO: improve formatDuration() API
+        assertFormatDuration("+999d23h59m59s999ms", 1342833071555L);
+        assertFormatDuration("-999d23h59m59s999ms", -1342833071555L);
+    }
+
     private void assertFormatDuration(String expected, long duration) {
         StringBuilder sb = new StringBuilder();
         TimeUtils.formatDuration(duration, sb);
diff --git a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
index deb9e67..4a809e0 100644
--- a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
+++ b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
@@ -66,7 +66,7 @@
 
         mLayout = new LinearLayout(this);
         mLayout.setOrientation(LinearLayout.VERTICAL);
-        mLayout.setHorizontalGravity(Gravity.LEFT);
+        mLayout.setHorizontalGravity(Gravity.START);
         mLayout.setLayoutParams(new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT));
diff --git a/core/tests/hosttests/Android.mk b/core/tests/hosttests/Android.mk
index 07d99cb..f26d401 100644
--- a/core/tests/hosttests/Android.mk
+++ b/core/tests/hosttests/Android.mk
@@ -16,17 +16,5 @@
 
 include $(CLEAR_VARS)
 
-#LOCAL_TEST_TYPE := hostSideOnly
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := FrameworkCoreHostTests
-
-LOCAL_JAVA_LIBRARIES := hosttestlib ddmlib-prebuilt junit
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
 # Build the test APKs using their own makefiles
 include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/core/tests/hosttests/README b/core/tests/hosttests/README
deleted file mode 100644
index d3bdb83..0000000
--- a/core/tests/hosttests/README
+++ /dev/null
@@ -1,6 +0,0 @@
-This dir contains tests which run on a host machine, and test aspects of
-package install etc via adb.
-
-To run, do:
-runtest framework-core-host
-
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
deleted file mode 100644
index c698e99..0000000
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.AndroidDebugBridge;
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.IShellOutputReceiver;
-import com.android.ddmlib.InstallException;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.MultiLineReceiver;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.SyncException;
-import com.android.ddmlib.TimeoutException;
-import com.android.ddmlib.SyncService.ISyncProgressMonitor;
-import com.android.ddmlib.testrunner.ITestRunListener;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.lang.Runtime;
-import java.lang.Process;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import junit.framework.Assert;
-
-/**
- * Set of tests that verify host side install cases
- */
-public class PackageManagerHostTestUtils extends Assert {
-
-    private static final String LOG_TAG = "PackageManagerHostTests";
-    private IDevice mDevice = null;
-
-    // TODO: get this value from Android Environment instead of hardcoding
-    private static final String APP_PRIVATE_PATH = "/data/app-private/";
-    private static final String DEVICE_APP_PATH = "/data/app/";
-    private static final String SDCARD_APP_PATH = "/mnt/secure/asec/";
-
-    private static final int MAX_WAIT_FOR_DEVICE_TIME = 120 * 1000;
-    private static final int WAIT_FOR_DEVICE_POLL_TIME = 10 * 1000;
-    private static final int MAX_WAIT_FOR_APP_LAUNCH_TIME = 60 * 1000;
-    private static final int WAIT_FOR_APP_LAUNCH_POLL_TIME = 5 * 1000;
-
-    // Install preference on the device-side
-    public static enum InstallLocPreference {
-        AUTO,
-        INTERNAL,
-        EXTERNAL
-    }
-
-    // Actual install location
-    public static enum InstallLocation {
-        DEVICE,
-        SDCARD
-    }
-
-    /**
-     * Constructor takes the device to use
-     * @param the device to use when performing operations
-     */
-    public PackageManagerHostTestUtils(IDevice device)
-    {
-          mDevice = device;
-    }
-
-    /**
-     * Disable default constructor
-     */
-    private PackageManagerHostTestUtils() {}
-
-    /**
-     * Returns the path on the device of forward-locked apps.
-     *
-     * @return path of forward-locked apps on the device
-     */
-    public static String getAppPrivatePath() {
-        return APP_PRIVATE_PATH;
-    }
-
-    /**
-     * Returns the path on the device of normal apps.
-     *
-     * @return path of forward-locked apps on the device
-     */
-    public static String getDeviceAppPath() {
-        return DEVICE_APP_PATH;
-    }
-
-    /**
-     * Returns the path of apps installed on the SD card.
-     *
-     * @return path of forward-locked apps on the device
-     */
-    public static String getSDCardAppPath() {
-        return SDCARD_APP_PATH;
-    }
-
-    /**
-     * Helper method to run tests and return the listener that collected the results.
-     *
-     * For the optional params, pass null to use the default values.
-
-     * @param pkgName Android application package for tests
-     * @param className (optional) The class containing the method to test
-     * @param methodName (optional) The method in the class of which to test
-     * @param runnerName (optional) The name of the TestRunner of the test on the device to be run
-     * @param params (optional) Any additional parameters to pass into the Test Runner
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @return the {@link CollectingTestRunListener}
-     */
-    private CollectingTestRunListener doRunTests(String pkgName, String className,
-            String methodName, String runnerName, Map<String, String> params) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName, runnerName,
-                mDevice);
-
-        if (className != null && methodName != null) {
-            testRunner.setMethodName(className, methodName);
-        }
-
-        // Add in any additional args to pass into the test
-        if (params != null) {
-            for (Entry<String, String> argPair : params.entrySet()) {
-                testRunner.addInstrumentationArg(argPair.getKey(), argPair.getValue());
-            }
-        }
-
-        CollectingTestRunListener listener = new CollectingTestRunListener();
-        try {
-            testRunner.run(listener);
-        } catch (IOException ioe) {
-            Log.w(LOG_TAG, "encountered IOException " + ioe);
-        }
-        return listener;
-    }
-
-    /**
-     * Runs the specified packages tests, and returns whether all tests passed or not.
-     *
-     * @param pkgName Android application package for tests
-     * @param className The class containing the method to test
-     * @param methodName The method in the class of which to test
-     * @param runnerName The name of the TestRunner of the test on the device to be run
-     * @param params Any additional parameters to pass into the Test Runner
-     * @return true if test passed, false otherwise.
-     */
-    public boolean runDeviceTestsDidAllTestsPass(String pkgName, String className,
-            String methodName, String runnerName, Map<String, String> params) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        CollectingTestRunListener listener = doRunTests(pkgName, className, methodName,
-                runnerName, params);
-        return listener.didAllTestsPass();
-    }
-
-    /**
-     * Runs the specified packages tests, and returns whether all tests passed or not.
-     *
-     * @param pkgName Android application package for tests
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @return true if every test passed, false otherwise.
-     */
-    public boolean runDeviceTestsDidAllTestsPass(String pkgName) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        CollectingTestRunListener listener = doRunTests(pkgName, null, null, null, null);
-        return listener.didAllTestsPass();
-    }
-
-    /**
-     * Helper method to push a file to device
-     * @param apkAppPrivatePath
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     */
-    public void pushFile(final String localFilePath, final String destFilePath)
-            throws IOException, SyncException, TimeoutException, AdbCommandRejectedException {
-        mDevice.getSyncService().pushFile(localFilePath,
-                destFilePath, new NullSyncProgressMonitor());
-    }
-
-    /**
-     * Helper method to install a file
-     * @param localFilePath the absolute file system path to file on local host to install
-     * @param reinstall set to <code>true</code> if re-install of app should be performed
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed
-     */
-    public void installFile(final String localFilePath, final boolean replace) throws IOException,
-            InstallException {
-        String result = mDevice.installPackage(localFilePath, replace);
-        assertEquals(null, result);
-    }
-
-    /**
-     * Helper method to install a file that should not be install-able
-     * @param localFilePath the absolute file system path to file on local host to install
-     * @param reinstall set to <code>true</code> if re-install of app should be performed
-     * @return the string output of the failed install attempt
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed
-     */
-    public String installFileFail(final String localFilePath, final boolean replace)
-            throws IOException, InstallException {
-        String result = mDevice.installPackage(localFilePath, replace);
-        assertNotNull(result);
-        return result;
-    }
-
-    /**
-     * Helper method to install a file to device as forward locked
-     * @param localFilePath the absolute file system path to file on local host to install
-     * @param reinstall set to <code>true</code> if re-install of app should be performed
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public String installFileForwardLocked(final String localFilePath, final boolean replace)
-            throws IOException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-        String remoteFilePath = mDevice.syncPackageToDevice(localFilePath);
-        InstallReceiver receiver = new InstallReceiver();
-        String cmd = String.format(replace ? "pm install -r -l \"%1$s\"" :
-                "pm install -l \"%1$s\"", remoteFilePath);
-        mDevice.executeShellCommand(cmd, receiver);
-        mDevice.removeRemotePackage(remoteFilePath);
-        return receiver.getErrorMessage();
-    }
-
-    /**
-     * Helper method to determine if file on device exists.
-     *
-     * @param destPath the absolute path of file on device to check
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesRemoteFileExist(String destPath) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String lsGrep = executeShellCommand(String.format("ls %s", destPath));
-        return !lsGrep.contains("No such file or directory");
-    }
-
-    /**
-     * Helper method to determine if file exists on the device containing a given string.
-     *
-     * @param destPath the absolute path of the file
-     * @return <code>true</code> if file exists containing given string,
-     *         <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesRemoteFileExistContainingString(String destPath, String searchString)
-            throws IOException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        String lsResult = executeShellCommand(String.format("ls %s", destPath));
-        return lsResult.contains(searchString);
-    }
-
-    /**
-     * Helper method to determine if package on device exists.
-     *
-     * @param packageName the Android manifest package to check.
-     * @return <code>true</code> if package exists, <code>false</code> otherwise
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesPackageExist(String packageName) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String pkgGrep = executeShellCommand(String.format("pm path %s", packageName));
-        return pkgGrep.contains("package:");
-    }
-
-    /**
-     * Determines if app was installed on device.
-     *
-     * @param packageName package name to check for
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesAppExistOnDevice(String packageName) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        return doesRemoteFileExistContainingString(DEVICE_APP_PATH, packageName);
-    }
-
-    /**
-     * Determines if app was installed on SD card.
-     *
-     * @param packageName package name to check for
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesAppExistOnSDCard(String packageName) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        return doesRemoteFileExistContainingString(SDCARD_APP_PATH, packageName);
-    }
-
-    /**
-     * Helper method to determine if app was installed on SD card.
-     *
-     * @param packageName package name to check for
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesAppExistAsForwardLocked(String packageName) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        return doesRemoteFileExistContainingString(APP_PRIVATE_PATH, packageName);
-    }
-
-    /**
-     * Waits for device's package manager to respond.
-     *
-     * @throws InterruptedException
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void waitForPackageManager() throws InterruptedException, IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "waiting for device");
-        int currentWaitTime = 0;
-        // poll the package manager until it returns something for android
-        while (!doesPackageExist("android")) {
-            Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
-            currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
-            if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
-                Log.e(LOG_TAG, "time out waiting for device");
-                throw new InterruptedException();
-            }
-        }
-    }
-
-    /**
-     * Helper to determine if the device is currently online and visible via ADB.
-     *
-     * @return true iff the device is currently available to ADB and online, false otherwise.
-     */
-    private boolean deviceIsOnline() {
-        AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
-        IDevice[] devices = bridge.getDevices();
-
-        for (IDevice device : devices) {
-            // only online if the device appears in the devices list, and its state is online
-            if ((mDevice != null) &&
-                    mDevice.getSerialNumber().equals(device.getSerialNumber()) &&
-                    device.isOnline()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Waits for device to be online (visible to ADB) before returning, or times out if we've
-     * waited too long. Note that this only means the device is visible via ADB, not that
-     * PackageManager is fully up and running yet.
-     *
-     * @throws InterruptedException
-     * @throws IOException
-     */
-    public void waitForDeviceToComeOnline() throws InterruptedException, IOException {
-        Log.i(LOG_TAG, "waiting for device to be online");
-        int currentWaitTime = 0;
-
-        // poll ADB until we see the device is online
-        while (!deviceIsOnline()) {
-            Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
-            currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
-            if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
-                Log.e(LOG_TAG, "time out waiting for device");
-                throw new InterruptedException();
-            }
-        }
-        // Note: if we try to access the device too quickly after it is "officially" online,
-        // there are sometimes strange issues where it's actually not quite ready yet,
-        // so we pause for a bit once more before actually returning.
-        Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
-    }
-
-    /**
-     * Queries package manager and waits until a package is launched (or times out)
-     *
-     * @param packageName The name of the package to wait to load
-     * @throws InterruptedException
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void waitForApp(String packageName) throws InterruptedException, IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "waiting for app to launch");
-        int currentWaitTime = 0;
-        // poll the package manager until it returns something for the package we're looking for
-        while (!doesPackageExist(packageName)) {
-            Thread.sleep(WAIT_FOR_APP_LAUNCH_POLL_TIME);
-            currentWaitTime += WAIT_FOR_APP_LAUNCH_POLL_TIME;
-            if (currentWaitTime > MAX_WAIT_FOR_APP_LAUNCH_TIME) {
-                Log.e(LOG_TAG, "time out waiting for app to launch: " + packageName);
-                throw new InterruptedException();
-            }
-        }
-    }
-
-    /**
-     * Helper method which executes a adb shell command and returns output as a {@link String}
-     * @return the output of the command
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public String executeShellCommand(String command) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, String.format("adb shell %s", command));
-        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-        mDevice.executeShellCommand(command, receiver);
-        String output = receiver.getOutput();
-        Log.i(LOG_TAG, String.format("Result: %s", output));
-        return output;
-    }
-
-    /**
-     * Helper method ensures we are in root mode on the host side. It returns only after
-     * PackageManager is actually up and running.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void runAdbRoot() throws IOException, InterruptedException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "adb root");
-        Runtime runtime = Runtime.getRuntime();
-        Process process = runtime.exec("adb root"); // adb should be in the path
-        BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
-
-        String nextLine = null;
-        while (null != (nextLine = output.readLine())) {
-            Log.i(LOG_TAG, nextLine);
-        }
-        process.waitFor();
-        waitForDeviceToComeOnline();
-        waitForPackageManager(); // now wait for package manager to actually load
-    }
-
-    /**
-     * Helper method which reboots the device and returns once the device is online again
-     * and package manager is up and running (note this function is synchronous to callers).
-     * @throws InterruptedException
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void rebootDevice() throws IOException, InterruptedException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String command = "reboot"; // no need for -s since mDevice is already tied to a device
-        Log.i(LOG_TAG, command);
-        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-        mDevice.executeShellCommand(command, receiver);
-        String output = receiver.getOutput();
-        Log.i(LOG_TAG, String.format("Result: %s", output));
-        waitForDeviceToComeOnline(); // wait for device to come online
-        runAdbRoot();
-    }
-
-    /**
-     * A {@link IShellOutputReceiver} which collects the whole shell output into one {@link String}
-     */
-    private class CollectingOutputReceiver extends MultiLineReceiver {
-
-        private StringBuffer mOutputBuffer = new StringBuffer();
-
-        public String getOutput() {
-            return mOutputBuffer.toString();
-        }
-
-        @Override
-        public void processNewLines(String[] lines) {
-            for (String line: lines) {
-                mOutputBuffer.append(line);
-                mOutputBuffer.append("\n");
-            }
-        }
-
-        public boolean isCancelled() {
-            return false;
-        }
-    }
-
-    private class NullSyncProgressMonitor implements ISyncProgressMonitor {
-        public void advance(int work) {
-            // ignore
-        }
-
-        public boolean isCanceled() {
-            // ignore
-            return false;
-        }
-
-        public void start(int totalWork) {
-            // ignore
-
-        }
-
-        public void startSubTask(String name) {
-            // ignore
-        }
-
-        public void stop() {
-            // ignore
-        }
-    }
-
-    // For collecting results from running device tests
-    public static class CollectingTestRunListener implements ITestRunListener {
-
-        private boolean mAllTestsPassed = true;
-        private String mTestRunErrorMessage = null;
-
-        public void testEnded(TestIdentifier test, Map<String, String> metrics) {
-            // ignore
-        }
-
-        public void testFailed(TestFailure status, TestIdentifier test,
-                String trace) {
-            Log.w(LOG_TAG, String.format("%s#%s failed: %s", test.getClassName(),
-                    test.getTestName(), trace));
-            mAllTestsPassed = false;
-        }
-
-        public void testRunEnded(long elapsedTime, Map<String, String> resultBundle) {
-            // ignore
-        }
-
-        public void testRunFailed(String errorMessage) {
-            Log.w(LOG_TAG, String.format("test run failed: %s", errorMessage));
-            mAllTestsPassed = false;
-            mTestRunErrorMessage = errorMessage;
-        }
-
-        public void testRunStarted(String runName, int testCount) {
-            // ignore
-        }
-
-        public void testRunStopped(long elapsedTime) {
-            // ignore
-        }
-
-        public void testStarted(TestIdentifier test) {
-            // ignore
-        }
-
-        boolean didAllTestsPass() {
-            return mAllTestsPassed;
-        }
-
-        /**
-         * Get the test run failure error message.
-         * @return the test run failure error message or <code>null</code> if test run completed.
-         */
-        String getTestRunErrorMessage() {
-            return mTestRunErrorMessage;
-        }
-    }
-
-    /**
-     * Output receiver for "pm install package.apk" command line.
-     *
-     */
-    private static final class InstallReceiver extends MultiLineReceiver {
-
-        private static final String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
-        private static final Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
-
-        private String mErrorMessage = null;
-
-        public InstallReceiver() {
-        }
-
-        @Override
-        public void processNewLines(String[] lines) {
-            for (String line : lines) {
-                if (line.length() > 0) {
-                    if (line.startsWith(SUCCESS_OUTPUT)) {
-                        mErrorMessage = null;
-                    } else {
-                        Matcher m = FAILURE_PATTERN.matcher(line);
-                        if (m.matches()) {
-                            mErrorMessage = m.group(1);
-                        }
-                    }
-                }
-            }
-        }
-
-        public boolean isCancelled() {
-            return false;
-        }
-
-        public String getErrorMessage() {
-            return mErrorMessage;
-        }
-    }
-
-    /**
-     * Helper method for installing an app to wherever is specified in its manifest, and
-     * then verifying the app was installed onto SD Card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param the path of the apk to install
-     * @param the name of the package
-     * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppAndVerifyExistsOnSDCard(String apkPath, String pkgName, boolean overwrite)
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        // Start with a clean slate if we're not overwriting
-        if (!overwrite) {
-            // cleanup test app just in case it already exists
-            mDevice.uninstallPackage(pkgName);
-            // grep for package to make sure its not installed
-            assertFalse(doesPackageExist(pkgName));
-        }
-
-        installFile(apkPath, overwrite);
-        assertTrue(doesAppExistOnSDCard(pkgName));
-        assertFalse(doesAppExistOnDevice(pkgName));
-        waitForPackageManager();
-
-        // grep for package to make sure it is installed
-        assertTrue(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for installing an app to wherever is specified in its manifest, and
-     * then verifying the app was installed onto device.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param the path of the apk to install
-     * @param the name of the package
-     * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppAndVerifyExistsOnDevice(String apkPath, String pkgName, boolean overwrite)
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        // Start with a clean slate if we're not overwriting
-        if (!overwrite) {
-            // cleanup test app just in case it already exists
-            mDevice.uninstallPackage(pkgName);
-            // grep for package to make sure its not installed
-            assertFalse(doesPackageExist(pkgName));
-        }
-
-        installFile(apkPath, overwrite);
-        assertFalse(doesAppExistOnSDCard(pkgName));
-        assertTrue(doesAppExistOnDevice(pkgName));
-        waitForPackageManager();
-
-        // grep for package to make sure it is installed
-        assertTrue(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for installing an app as forward-locked, and
-     * then verifying the app was installed in the proper forward-locked location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param the path of the apk to install
-     * @param the name of the package
-     * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
-     * @throws InterruptedException if the thread was interrupted
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     */
-    public void installFwdLockedAppAndVerifyExists(String apkPath,
-            String pkgName, boolean overwrite) throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        // Start with a clean slate if we're not overwriting
-        if (!overwrite) {
-            // cleanup test app just in case it already exists
-            mDevice.uninstallPackage(pkgName);
-            // grep for package to make sure its not installed
-            assertFalse(doesPackageExist(pkgName));
-        }
-
-        String result = installFileForwardLocked(apkPath, overwrite);
-        assertEquals(null, result);
-        assertTrue(doesAppExistAsForwardLocked(pkgName));
-        assertFalse(doesAppExistOnSDCard(pkgName));
-        waitForPackageManager();
-
-        // grep for package to make sure it is installed
-        assertTrue(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for uninstalling an app.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param pkgName package name to uninstall
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the uninstall failed.
-     */
-    public void uninstallApp(String pkgName) throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        mDevice.uninstallPackage(pkgName);
-        // make sure its not installed anymore
-        assertFalse(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for clearing any installed non-system apps.
-     * Useful ensuring no non-system apps are installed, and for cleaning up stale files that
-     * may be lingering on the system for whatever reason.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the uninstall failed.
-     */
-    public void wipeNonSystemApps() throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException, InstallException {
-      String allInstalledPackages = executeShellCommand("pm list packages -f");
-      BufferedReader outputReader = new BufferedReader(new StringReader(allInstalledPackages));
-
-      // First use Package Manager to uninstall all non-system apps
-      String currentLine = null;
-      while ((currentLine = outputReader.readLine()) != null) {
-          // Skip over any system apps...
-          if (currentLine.contains("/system/")) {
-              continue;
-          }
-          String packageName = currentLine.substring(currentLine.indexOf('=') + 1);
-          mDevice.uninstallPackage(packageName);
-      }
-      // Make sure there are no stale app files under these directories
-      executeShellCommand(String.format("rm %s*", SDCARD_APP_PATH, "*"));
-      executeShellCommand(String.format("rm %s*", DEVICE_APP_PATH, "*"));
-      executeShellCommand(String.format("rm %s*", APP_PRIVATE_PATH, "*"));
-    }
-
-    /**
-     * Sets the device's install location preference.
-     *
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void setDevicePreferredInstallLocation(InstallLocPreference pref) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String command = "pm setInstallLocation %d";
-        int locValue = 0;
-        switch (pref) {
-            case INTERNAL:
-                locValue = 1;
-                break;
-            case EXTERNAL:
-                locValue = 2;
-                break;
-            default: // AUTO
-                locValue = 0;
-                break;
-        }
-        executeShellCommand(String.format(command, locValue));
-    }
-
-    /**
-     * Gets the device's install location preference.
-     *
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public InstallLocPreference getDevicePreferredInstallLocation() throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String result = executeShellCommand("pm getInstallLocation");
-        if (result.indexOf('0') != -1) {
-            return InstallLocPreference.AUTO;
-        }
-        else if (result.indexOf('1') != -1) {
-            return InstallLocPreference.INTERNAL;
-        }
-        else {
-            return InstallLocPreference.EXTERNAL;
-        }
-    }
-}
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java
deleted file mode 100644
index 22a2be6..0000000
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.InstallException;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.SyncException;
-import com.android.ddmlib.TimeoutException;
-import com.android.hosttest.DeviceTestCase;
-import com.android.hosttest.DeviceTestSuite;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.Test;
-
-/**
- * Set of tests that verify host side install cases
- */
-public class PackageManagerHostTests extends DeviceTestCase {
-
-    private static final String LOG_TAG = "PackageManagerHostTests";
-    private PackageManagerHostTestUtils mPMHostUtils = null;
-
-    private String appPrivatePath = null;
-    private String deviceAppPath = null;
-    private String sdcardAppPath = null;
-
-    // Various test files and their corresponding package names...
-
-    // testPushAppPrivate constants
-    // these constants must match values defined in test-apps/SimpleTestApp
-    private static final String SIMPLE_APK = "SimpleTestApp.apk";
-    private static final String SIMPLE_PKG = "com.android.framework.simpletestapp";
-
-    // Apk with install location set to auto
-    private static final String AUTO_LOC_APK = "AutoLocTestApp.apk";
-    private static final String AUTO_LOC_PKG = "com.android.framework.autoloctestapp";
-    // Apk with install location set to internalOnly
-    private static final String INTERNAL_LOC_APK = "InternalLocTestApp.apk";
-    private static final String INTERNAL_LOC_PKG = "com.android.framework.internalloctestapp";
-    // Apk with install location set to preferExternal
-    private static final String EXTERNAL_LOC_APK = "ExternalLocTestApp.apk";
-    private static final String EXTERNAL_LOC_PKG = "com.android.framework.externalloctestapp";
-    // Apk with install location set to auto (2 versions, for update testing)
-    private static final String AUTO_LOC_VERSION_V1_APK = "AutoLocVersionedTestApp_v1.apk";
-    private static final String AUTO_LOC_VERSION_V2_APK = "AutoLocVersionedTestApp_v2.apk";
-    private static final String AUTO_LOC_VERSION_PKG =
-            "com.android.framework.autolocversionedtestapp";
-    // Apk with install location set to preferExternal (2 versions, for update testing)
-    private static final String EXTERNAL_LOC_VERSION_V1_APK = "ExternalLocVersionedTestApp_v1.apk";
-    private static final String EXTERNAL_LOC_VERSION_V2_APK = "ExternalLocVersionedTestApp_v2.apk";
-    private static final String EXTERNAL_LOC_VERSION_PKG =
-            "com.android.framework.externallocversionedtestapp";
-    // Apk with install location set to auto (2 versions, for update testing)
-    private static final String NO_LOC_VERSION_V1_APK = "NoLocVersionedTestApp_v1.apk";
-    private static final String NO_LOC_VERSION_V2_APK = "NoLocVersionedTestApp_v2.apk";
-    private static final String NO_LOC_VERSION_PKG =
-            "com.android.framework.nolocversionedtestapp";
-    // Apk with no install location set
-    private static final String NO_LOC_APK = "NoLocTestApp.apk";
-    private static final String NO_LOC_PKG = "com.android.framework.noloctestapp";
-    // Apk with 2 different versions - v1 is set to external, v2 has no location setting
-    private static final String UPDATE_EXTERNAL_LOC_V1_EXT_APK
-            = "UpdateExternalLocTestApp_v1_ext.apk";
-    private static final String UPDATE_EXTERNAL_LOC_V2_NONE_APK
-            = "UpdateExternalLocTestApp_v2_none.apk";
-    private static final String UPDATE_EXTERNAL_LOC_PKG
-            = "com.android.framework.updateexternalloctestapp";
-    // Apk with 2 different versions - v1 is set to external, v2 is set to internalOnly
-    private static final String UPDATE_EXT_TO_INT_LOC_V1_EXT_APK
-            = "UpdateExtToIntLocTestApp_v1_ext.apk";
-    private static final String UPDATE_EXT_TO_INT_LOC_V2_INT_APK
-            = "UpdateExtToIntLocTestApp_v2_int.apk";
-    private static final String UPDATE_EXT_TO_INT_LOC_PKG
-            = "com.android.framework.updateexttointloctestapp";
-    // Apk set to preferExternal, with Access Fine Location permissions set in its manifest
-    private static final String FL_PERMS_APK = "ExternalLocPermsFLTestApp.apk";
-    private static final String FL_PERMS_PKG = "com.android.framework.externallocpermsfltestapp";
-    // Apk set to preferExternal, with all permissions set in manifest
-    private static final String ALL_PERMS_APK = "ExternalLocAllPermsTestApp.apk";
-    private static final String ALL_PERMS_PKG = "com.android.framework.externallocallpermstestapp";
-    // Apks with the same package name, but install location set to
-    // one of: Internal, External, Auto, or None
-    private static final String VERSATILE_LOC_PKG = "com.android.framework.versatiletestapp";
-    private static final String VERSATILE_LOC_INTERNAL_APK = "VersatileTestApp_Internal.apk";
-    private static final String VERSATILE_LOC_EXTERNAL_APK = "VersatileTestApp_External.apk";
-    private static final String VERSATILE_LOC_AUTO_APK = "VersatileTestApp_Auto.apk";
-    private static final String VERSATILE_LOC_NONE_APK = "VersatileTestApp_None.apk";
-    // Apks with shared UserID
-    private static final String SHARED_PERMS_APK = "ExternalSharedPermsTestApp.apk";
-    private static final String SHARED_PERMS_PKG
-            = "com.android.framework.externalsharedpermstestapp";
-    private static final String SHARED_PERMS_FL_APK = "ExternalSharedPermsFLTestApp.apk";
-    private static final String SHARED_PERMS_FL_PKG
-            = "com.android.framework.externalsharedpermsfltestapp";
-    private static final String SHARED_PERMS_BT_APK = "ExternalSharedPermsBTTestApp.apk";
-    private static final String SHARED_PERMS_BT_PKG
-            = "com.android.framework.externalsharedpermsbttestapp";
-    // Apk with shared UserID, but signed with a different cert (the media cert)
-    private static final String SHARED_PERMS_DIFF_KEY_APK = "ExternalSharedPermsDiffKeyTestApp.apk";
-    private static final String SHARED_PERMS_DIFF_KEY_PKG
-            = "com.android.framework.externalsharedpermsdiffkeytestapp";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // ensure apk path has been set before test is run
-        assertNotNull(getTestAppPath());
-
-        // setup the PackageManager host tests utilities class, and get various paths we'll need...
-        mPMHostUtils = new PackageManagerHostTestUtils(getDevice());
-        appPrivatePath = mPMHostUtils.getAppPrivatePath();
-        deviceAppPath = mPMHostUtils.getDeviceAppPath();
-        sdcardAppPath = mPMHostUtils.getSDCardAppPath();
-
-        // Ensure the default is set to let the system decide where to install apps
-        // (It's ok for individual tests to override and change this during their test, but should
-        // reset it back when they're done)
-        mPMHostUtils.setDevicePreferredInstallLocation(
-                PackageManagerHostTestUtils.InstallLocPreference.AUTO);
-    }
-
-    /**
-     * Get the absolute file system location of test app with given filename
-     * @param fileName the file name of the test app apk
-     * @return {@link String} of absolute file path
-     */
-    public String getTestAppFilePath(String fileName) {
-        return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
-    }
-
-    public static Test suite() {
-        return new DeviceTestSuite(PackageManagerHostTests.class);
-    }
-
-    /**
-     * Regression test to verify that pushing an apk to the private app directory doesn't install
-     * the app, and otherwise cause the system to blow up.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testPushAppPrivate() throws IOException, InterruptedException, InstallException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            SyncException {
-        Log.i(LOG_TAG, "testing pushing an apk to /data/app-private");
-        final String apkAppPrivatePath =  appPrivatePath + SIMPLE_APK;
-
-        // cleanup test app just in case it was accidently installed
-        getDevice().uninstallPackage(SIMPLE_PKG);
-        mPMHostUtils.executeShellCommand("stop");
-        mPMHostUtils.pushFile(getTestAppFilePath(SIMPLE_APK), apkAppPrivatePath);
-
-        // sanity check to make sure file is there
-        assertTrue(mPMHostUtils.doesRemoteFileExist(apkAppPrivatePath));
-        mPMHostUtils.executeShellCommand("start");
-
-        mPMHostUtils.waitForPackageManager();
-
-        // grep for package to make sure its not installed
-        assertFalse(mPMHostUtils.doesPackageExist(SIMPLE_PKG));
-        // ensure it has been deleted from app-private
-        assertFalse(mPMHostUtils.doesRemoteFileExist(apkAppPrivatePath));
-    }
-
-    /**
-     * Helper to do a standard install of an apk and verify it installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param apkName the file name of the test app apk
-     * @param pkgName the package name of the test app apk
-     * @param expectedLocation the file name of the test app apk
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    private void doStandardInstall(String apkName, String pkgName,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-
-        if (expectedLocation == PackageManagerHostTestUtils.InstallLocation.DEVICE) {
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(apkName), pkgName, false);
-        }
-        else {
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(apkName), pkgName, false);
-        }
-    }
-
-    /**
-     * Installs the Auto app using the preferred device install location specified,
-     * and verifies it was installed on the device.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param preference the device's preferred location of where to install apps
-     * @param expectedLocation the expected location of where the apk was installed
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-                PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(preference);
-
-            doStandardInstall(AUTO_LOC_APK, AUTO_LOC_PKG, expectedLocation);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(AUTO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=auto
-     * will install the app to the device when device's preference is auto.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppAutoLocPrefIsAuto() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=auto, prefer=auto gets installed on device");
-        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=auto
-     * will install the app to the device when device's preference is internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppAutoLocPrefIsInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=auto, prefer=internal gets installed on device");
-        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=auto
-     * will install the app to the SD card when device's preference is external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppAutoLocPrefIsExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=auto, prefer=external gets installed on device");
-        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Installs the Internal app using the preferred device install location specified,
-     * and verifies it was installed to the location expected.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param preference the device's preferred location of where to install apps
-     * @param expectedLocation the expected location of where the apk was installed
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the (un)install failed.
-     */
-    public void installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(preference);
-
-            doStandardInstall(INTERNAL_LOC_APK, INTERNAL_LOC_PKG, expectedLocation);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
-     * will install the app to the device when device's preference is auto.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppInternalLocPrefIsAuto() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=internal, prefer=auto gets installed on device");
-        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
-     * will install the app to the device when device's preference is internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppInternalLocPrefIsInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=internal, prefer=internal is installed on device");
-        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
-     * will install the app to the device when device's preference is external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppInternalLocPrefIsExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=internal, prefer=external is installed on device");
-        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the SD card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param preference the device's preferred location of where to install apps
-     * @param expectedLocation the expected location of where the apk was installed
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(preference);
-
-            doStandardInstall(EXTERNAL_LOC_APK, EXTERNAL_LOC_PKG, expectedLocation);
-
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the device when device's preference is auto.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppExternalLocPrefIsAuto() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=external, pref=auto gets installed on SD Card");
-        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
-                PackageManagerHostTestUtils.InstallLocation.SDCARD);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the device when device's preference is internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppExternalLocPrefIsInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=external, pref=internal gets installed on SD Card");
-        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.SDCARD);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the device when device's preference is external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppExternalLocPrefIsExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=external, pref=external gets installed on SD Card");
-        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.SDCARD);
-    }
-
-    /**
-     * Regression test to verify that an app without installLocation in its manifest
-     * will install the app to the device by default when the system default pref is to let the
-     * system decide.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppNoLocPrefIsAuto() throws IOException, InterruptedException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            InstallException {
-        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on device");
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(
-                    PackageManagerHostTestUtils.InstallLocPreference.AUTO);
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app without installLocation in its manifest
-     * will install the app to the device by default when the system default pref is to install
-     * external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppNoLocPrefIsExternal() throws IOException, InterruptedException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            InstallException {
-        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on SD card");
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(
-                    PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app without installLocation in its manifest
-     * will install the app to the device by default when the system default pref is to install
-     * internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppNoLocPrefIsInternal() throws IOException, InterruptedException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            InstallException {
-        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on device");
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(
-                    PackageManagerHostTestUtils.InstallLocPreference.INTERNAL);
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its installLocation set to internal that is
-     * forward-locked will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppInternal() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with installLoc set to Internal gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(INTERNAL_LOC_APK), INTERNAL_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its installLocation set to external that is
-     * forward-locked will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppExternal() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with installLoc set to Internal gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(INTERNAL_LOC_APK), INTERNAL_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its installLocation set to external that is
-     * forward-locked will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppAuto() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with installLoc set to Auto gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(AUTO_LOC_APK), AUTO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(AUTO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with no installLocation set and is
-     * forward-locked installed will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppNone() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with no installLoc set gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that we can install an app onto the device,
-     * uninstall it, and reinstall it onto the SD card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    // TODO: This currently relies on the app's manifest to switch from device to
-    // SD card install locations. We might want to make Device's installPackage()
-    // accept a installLocation flag so we can install a package to the
-    // destination of our choosing.
-    public void testReinstallInternalToExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing an app first to the device, then to the SD Card");
-
-        try {
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(VERSATILE_LOC_INTERNAL_APK), VERSATILE_LOC_PKG, false);
-            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(VERSATILE_LOC_EXTERNAL_APK), VERSATILE_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that we can install an app onto the SD Card,
-     * uninstall it, and reinstall it onto the device.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    // TODO: This currently relies on the app's manifest to switch from device to
-    // SD card install locations. We might want to make Device's installPackage()
-    // accept a installLocation flag so we can install a package to the
-    // destination of our choosing.
-    public void testReinstallExternalToInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing an app first to the SD Care, then to the device");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(VERSATILE_LOC_EXTERNAL_APK), VERSATILE_LOC_PKG, false);
-            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-            // then replace the app with one marked for internalOnly
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(VERSATILE_LOC_INTERNAL_APK), VERSATILE_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-          mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating an app on the SD card will install
-     * the update onto the SD card as well when location is set to external for both versions
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testUpdateBothExternal() throws IOException, InterruptedException, InstallException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V1_APK), EXTERNAL_LOC_VERSION_PKG, false);
-            // now replace the app with one where the location is still set to preferExternal
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V2_APK), EXTERNAL_LOC_VERSION_PKG, true);
-        }
-        // cleanup test app
-        finally {
-          mPMHostUtils.uninstallApp(EXTERNAL_LOC_VERSION_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating an app on the SD card will install
-     * the update onto the SD card as well when location is not explicitly set in the
-     * updated apps' manifest file.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testUpdateToSDCard() throws IOException, InterruptedException, InstallException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    UPDATE_EXTERNAL_LOC_V1_EXT_APK), UPDATE_EXTERNAL_LOC_PKG, false);
-            // now replace the app with one where the location is blank (app should stay external)
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    UPDATE_EXTERNAL_LOC_V2_NONE_APK), UPDATE_EXTERNAL_LOC_PKG, true);
-        }
-        // cleanup test app
-        finally {
-          mPMHostUtils.uninstallApp(UPDATE_EXTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating an app on the SD card will install
-     * the update onto the device if the manifest has changed to installLocation=internalOnly
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testUpdateSDCardToDevice() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card to the Device through manifest change");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    UPDATE_EXT_TO_INT_LOC_V1_EXT_APK), UPDATE_EXT_TO_INT_LOC_PKG, false);
-            // now replace the app with an update marked for internalOnly...(should move internal)
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(getTestAppFilePath(
-                    UPDATE_EXT_TO_INT_LOC_V2_INT_APK), UPDATE_EXT_TO_INT_LOC_PKG, true);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(UPDATE_EXT_TO_INT_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that installing and updating a forward-locked app will install
-     * the update onto the device's forward-locked location
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndUpdateExternalLocForwardLockedApp()
-            throws IOException, InterruptedException, InstallException, SyncException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating a forward-locked app marked preferExternal");
-
-        try {
-            // first try to install the forward-locked app externally
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V1_APK), EXTERNAL_LOC_VERSION_PKG, false);
-            // now replace the app with an update marked for internalOnly and as forward locked
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V2_APK), EXTERNAL_LOC_VERSION_PKG, true);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(EXTERNAL_LOC_VERSION_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating a forward-locked app will install
-     * the update onto the device's forward-locked location
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndUpdateNoLocForwardLockedApp()
-            throws IOException, InterruptedException, InstallException, SyncException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating a forward-locked app with no installLocation pref set");
-
-        try {
-            // install the app
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    NO_LOC_VERSION_V1_APK), NO_LOC_VERSION_PKG, false);
-            // now replace the app with an update marked for internalOnly...
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    NO_LOC_VERSION_V2_APK), NO_LOC_VERSION_PKG, true);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(NO_LOC_VERSION_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with all permissions set can be installed on SD card
-     * and then launched without crashing.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchAllPermsAppOnSD()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with all perms set, installed on SD card");
-
-        try {
-            // install the app
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    ALL_PERMS_APK), ALL_PERMS_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(ALL_PERMS_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(ALL_PERMS_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with ACCESS_FINE_LOCATION (GPS) permissions can
-     * run without permissions errors.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchFLPermsAppOnSD()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with location perms set, installed on SD card");
-
-        try {
-            // install the app and verify we can launch it without permissions errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with BLUE_TOOTH permissions can
-     * run without permissions errors.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchBTPermsAppOnSD()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with bluetooth perms set, installed on SD card");
-
-        try {
-            // install the app and verify we can launch it without permissions errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_BT_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that a shared app with no explicit permissions throws a
-     * SecurityException when launched if its other shared apps are not installed.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchSharedPermsAppOnSD_NoPerms()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with no explicit perms set, installed on SD card");
-
-        try {
-            // Make sure the 2 shared apps with needed permissions are not installed...
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-
-            // now install the app and see if when we launch it we get a permissions error
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
-
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assertEquals("Shared perms app should fail to run", false, testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that a shared app with no explicit permissions can run if its other
-     * shared apps are installed.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchSharedPermsAppOnSD_GrantedPerms()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with no explicit perms set, installed on SD card");
-
-        try {
-            // install the 2 shared apps with needed permissions first
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
-
-            // now install the test app and see if we can launch it without errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with ACCESS_FINE_LOCATION (GPS) permissions can
-     * run without permissions errors even after a reboot
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchFLPermsAppOnSD_Reboot()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with location perms set, installed on SD card");
-
-        try {
-            // install the app and verify we can launch it without permissions errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
-            assert(testsPassed);
-
-            mPMHostUtils.rebootDevice();
-
-            testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that a shared app with no explicit permissions can run if its other
-     * shared apps are installed, even after a reboot.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchSharedPermsAppOnSD_Reboot()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app on SD, with no explicit perms set after reboot");
-
-        try {
-            // install the 2 shared apps with needed permissions first
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
-
-            // now install the test app and see if we can launch it without errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assert(testsPassed);
-
-            // reboot
-            mPMHostUtils.rebootDevice();
-
-            // Verify we can still launch the app
-            testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-}
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java b/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java
deleted file mode 100644
index a2a5dd3..0000000
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.InstallException;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.TimeoutException;
-import com.android.hosttest.DeviceTestCase;
-import com.android.hosttest.DeviceTestSuite;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.Test;
-
-/**
- * Set of tests that verify host side stress scenarios (large apps, multiple upgrades, etc.)
- */
-public class PackageManagerStressHostTests extends DeviceTestCase {
-
-    private static final String LOG_TAG = "PackageManagerStressHostTests";
-    private PackageManagerHostTestUtils mPMHostUtils = null;
-
-    // Path to the app repository and various subdirectories of it
-    // Note: These stress tests require large apks that cannot be checked into the tree.
-    // These variables define static locations that point to existing APKs (not built from
-    // the tree) which can be used by the the stress tests in this file.
-    private static final String LARGE_APPS_DIRECTORY_NAME = "largeApps";
-    private static final String MISC_APPS_DIRECTORY_NAME = "miscApps";
-    private static final String VERSIONED_APPS_DIRECTORY_NAME = "versionedApps";
-    private static final String MANY_APPS_DIRECTORY_NAME = "manyApps";
-
-    // Note: An external environment variable "ANDROID_TEST_APP_REPOSITORY" must be set
-    // which points to the root location of the app respository.
-    private static String AppRepositoryPath = null;
-
-    // Large apps (>1mb) - filenames and their corresponding package names:
-    private static enum APK {
-            FILENAME,
-            PACKAGENAME;
-    }
-    private static final String[][] LARGE_APPS = {
-       {"External1mb.apk", "com.appsonsd.mytests.External1mb"},
-       {"External2mb.apk", "com.appsonsd.mytests.External2mb"},
-       {"External3mb.apk", "com.appsonsd.mytests.External3mb"},
-       {"External4mb.apk", "com.appsonsd.mytests.External4mb"},
-       {"External5mb.apk", "com.appsonsd.mytests.External5mb"},
-       {"External6mb.apk", "com.appsonsd.mytests.External6mb"},
-       {"External7mb.apk", "com.appsonsd.mytests.External7mb"},
-       {"External8mb.apk", "com.appsonsd.mytests.External8mb"},
-       {"External9mb.apk", "com.appsonsd.mytests.External9mb"},
-       {"External10mb.apk", "com.appsonsd.mytests.External10mb"},
-       {"External16mb.apk", "com.appsonsd.mytests.External16mb"},
-       {"External28mb.apk", "com.appsonsd.mytests.External28mb"},
-       {"External34mb.apk", "com.appsonsd.mytests.External34mb"},
-       {"External46mb.apk", "com.appsonsd.mytests.External46mb"},
-       {"External58mb.apk", "com.appsonsd.mytests.External58mb"},
-       {"External65mb.apk", "com.appsonsd.mytests.External65mb"},
-       {"External72mb.apk", "com.appsonsd.mytests.External72mb"},
-       {"External79mb.apk", "com.appsonsd.mytests.External79mb"},
-       {"External86mb.apk", "com.appsonsd.mytests.External86mb"},
-       {"External93mb.apk", "com.appsonsd.mytests.External93mb"}};
-
-    // Various test files and their corresponding package names
-    private static final String AUTO_LOC_APK = "Auto241kb.apk";
-    private static final String AUTO_LOC_PKG = "com.appsonsd.mytests.Auto241kb";
-    private static final String INTERNAL_LOC_APK = "Internal781kb.apk";
-    private static final String INTERNAL_LOC_PKG = "com.appsonsd.mytests.Internal781kb";
-    private static final String EXTERNAL_LOC_APK = "External931kb.apk";
-    private static final String EXTERNAL_LOC_PKG = "com.appsonsd.mytests.External931kb";
-    private static final String NO_LOC_APK = "Internal751kb_EclairSDK.apk";
-    private static final String NO_LOC_PKG = "com.appsonsd.mytests.Internal751kb_EclairSDK";
-    // Versioned test apps
-    private static final String VERSIONED_APPS_FILENAME_PREFIX = "External455kb_v";
-    private static final String VERSIONED_APPS_PKG = "com.appsonsd.mytests.External455kb";
-    private static final int VERSIONED_APPS_START_VERSION = 1;  // inclusive
-    private static final int VERSIONED_APPS_END_VERSION = 250;  // inclusive
-    // Large number of app installs
-    // @TODO: increase the max when we can install more apps
-    private static final int MANY_APPS_START = 1;
-    private static final int MANY_APPS_END = 100;
-    private static final String MANY_APPS_PKG_PREFIX = "com.appsonsd.mytests.External49kb_";
-    private static final String MANY_APPS_APK_PREFIX = "External49kb_";
-
-    public static Test suite() {
-        return new DeviceTestSuite(PackageManagerStressHostTests.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        // setup the PackageManager host tests utilities class, and get various paths we'll need...
-        mPMHostUtils = new PackageManagerHostTestUtils(getDevice());
-        AppRepositoryPath = System.getenv("ANDROID_TEST_APP_REPOSITORY");
-        assertNotNull(AppRepositoryPath);
-
-        // Make sure path ends with a separator
-        if (!AppRepositoryPath.endsWith(File.separator)) {
-            AppRepositoryPath += File.separator;
-        }
-    }
-
-    /**
-     * Get the absolute file system location of repository test app with given filename
-     * @param fileName the file name of the test app apk
-     * @return {@link String} of absolute file path
-     */
-    private String getRepositoryTestAppFilePath(String fileDirectory, String fileName) {
-        return String.format("%s%s%s%s", AppRepositoryPath, fileDirectory,
-                File.separator, fileName);
-    }
-
-    /**
-     * Get the absolute file system location of test app with given filename
-     * @param fileName the file name of the test app apk
-     * @return {@link String} of absolute file path
-     */
-    public String getTestAppFilePath(String fileName) {
-        return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
-    }
-
-    /**
-     * Stress test to verify that we can update an app multiple times on the SD card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testUpdateAppManyTimesOnSD() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on SD numerous times");
-
-        // cleanup test app just in case it already exists
-        mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG);
-        // grep for package to make sure its not installed
-        assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
-
-        try {
-            for (int i = VERSIONED_APPS_START_VERSION; i <= VERSIONED_APPS_END_VERSION; ++i) {
-                String currentApkName = String.format("%s%d.apk",
-                        VERSIONED_APPS_FILENAME_PREFIX, i);
-
-                Log.i(LOG_TAG, "Installing app " + currentApkName);
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(VERSIONED_APPS_DIRECTORY_NAME,
-                        currentApkName), true);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(VERSIONED_APPS_PKG));
-                assertTrue(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
-            }
-        }
-        finally {
-            // cleanup test app
-            mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG);
-            // grep for package to make sure its not installed
-            assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
-        }
-    }
-
-    /**
-     * Stress test to verify that an app can be installed, uninstalled, and
-     * reinstalled on SD many times.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testUninstallReinstallAppOnSDManyTimes() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
-
-        // cleanup test app just in case it was already exists
-        mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
-        // grep for package to make sure its not installed
-        assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
-
-        for (int i = 0; i <= 500; ++i) {
-            Log.i(LOG_TAG, "Installing app");
-
-            try {
-                // install the app
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(MISC_APPS_DIRECTORY_NAME,
-                        EXTERNAL_LOC_APK), false);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(EXTERNAL_LOC_PKG));
-                assertTrue(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
-            }
-            finally {
-                // now uninstall the app
-                Log.i(LOG_TAG, "Uninstalling app");
-                mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
-                mPMHostUtils.waitForPackageManager();
-                assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
-            }
-        }
-    }
-
-    /**
-     * Stress test to verify that we can install, 20 large apps (>1mb each)
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testInstallManyLargeAppsOnSD() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing 20 large apps onto the sd card");
-
-        try {
-            // Install all the large apps
-            for (int i=0; i < LARGE_APPS.length; ++i) {
-                String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()];
-                String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()];
-
-                // cleanup test app just in case it already exists
-                mPMHostUtils.uninstallApp(pkgName);
-                // grep for package to make sure its not installed
-                assertFalse(mPMHostUtils.doesPackageExist(pkgName));
-
-                Log.i(LOG_TAG, "Installing app " + apkName);
-                // install the app
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(LARGE_APPS_DIRECTORY_NAME,
-                        apkName), false);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(pkgName));
-                assertTrue(mPMHostUtils.doesPackageExist(pkgName));
-            }
-        }
-        finally {
-            // Cleanup - ensure we uninstall all large apps if they were installed
-            for (int i=0; i < LARGE_APPS.length; ++i) {
-                String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()];
-                String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()];
-
-                Log.i(LOG_TAG, "Uninstalling app " + apkName);
-                // cleanup test app just in case it was accidently installed
-                mPMHostUtils.uninstallApp(pkgName);
-                // grep for package to make sure its not installed anymore
-                assertFalse(mPMHostUtils.doesPackageExist(pkgName));
-                assertFalse(mPMHostUtils.doesAppExistOnSDCard(pkgName));
-            }
-        }
-    }
-
-    /**
-     * Stress test to verify that we can install many small apps onto SD.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testInstallManyAppsOnSD() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing 500 small apps onto SD");
-
-        try {
-            for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) {
-                String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i);
-
-                // cleanup test app just in case it already exists
-                mPMHostUtils.uninstallApp(currentPkgName);
-                // grep for package to make sure its not installed
-                assertFalse(mPMHostUtils.doesPackageExist(currentPkgName));
-
-                String currentApkName = String.format("%s%d.apk", MANY_APPS_APK_PREFIX, i);
-                Log.i(LOG_TAG, "Installing app " + currentApkName);
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(MANY_APPS_DIRECTORY_NAME,
-                        currentApkName), true);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(currentPkgName));
-                assertTrue(mPMHostUtils.doesPackageExist(currentPkgName));
-            }
-        }
-        finally {
-            for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) {
-                String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i);
-
-                // cleanup test app
-                mPMHostUtils.uninstallApp(currentPkgName);
-                // grep for package to make sure its not installed
-                assertFalse(mPMHostUtils.doesPackageExist(currentPkgName));
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java b/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
deleted file mode 100644
index a94555c..0000000
--- a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.pm.PackageManagerHostTestUtils;
-
-import com.android.ddmlib.Log;
-import com.android.hosttest.DeviceTestCase;
-import com.android.hosttest.DeviceTestSuite;
-
-import java.io.File;
-import java.util.Hashtable;
-
-import junit.framework.Test;
-
-/**
- * Host-based tests of the DownloadManager API. (Uses a device-based app to actually invoke the
- * various tests.)
- */
-public class DownloadManagerHostTests extends DeviceTestCase {
-    protected PackageManagerHostTestUtils mPMUtils = null;
-
-    private static final String LOG_TAG = "android.net.DownloadManagerHostTests";
-    private static final String FILE_DOWNLOAD_APK = "DownloadManagerTestApp.apk";
-    private static final String FILE_DOWNLOAD_PKG = "com.android.frameworks.downloadmanagertests";
-    private static final String FILE_DOWNLOAD_CLASS =
-            "com.android.frameworks.downloadmanagertests.DownloadManagerTestApp";
-    private static final String DOWNLOAD_TEST_RUNNER_NAME =
-            "com.android.frameworks.downloadmanagertests.DownloadManagerTestRunner";
-
-    // Extra parameters to pass to the TestRunner
-    private static final String EXTERNAL_DOWNLOAD_URI_KEY = "external_download_uri";
-    // Note: External environment variable ANDROID_TEST_EXTERNAL_URI must be set to point to the
-    // external URI under which the files downloaded by the tests can be found. Note that the Uri
-    // must be accessible by the device during a test run. Correspondingly,
-    // ANDROID_TEST_EXTERNAL_LARGE_URI should point to the external URI of the folder containing
-    // large files.
-    private static String externalDownloadUriValue = null;
-
-    Hashtable<String, String> mExtraParams = null;
-
-    public static Test suite() {
-        return new DeviceTestSuite(DownloadManagerHostTests.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // ensure apk path has been set before test is run
-        assertNotNull(getTestAppPath());
-        mPMUtils = new PackageManagerHostTestUtils(getDevice());
-        externalDownloadUriValue = System.getenv("ANDROID_TEST_EXTERNAL_URI");
-        assertNotNull(externalDownloadUriValue);
-        mExtraParams = getExtraParams();
-    }
-
-    /**
-     * Helper function to get extra params that can be used to pass into the helper app.
-     */
-    protected Hashtable<String, String> getExtraParams() {
-        Hashtable<String, String> extraParams = new Hashtable<String, String>();
-        extraParams.put(EXTERNAL_DOWNLOAD_URI_KEY, externalDownloadUriValue);
-        return extraParams;
-    }
-
-    /**
-     * Tests that a large download over WiFi
-     * @throws Exception if the test failed at any point
-     */
-    public void testLargeDownloadOverWiFi() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runLargeDownloadOverWiFi", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-
-        assertTrue("Failed to install large file over WiFi in < 10 minutes!", testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to initiate a download on the device, reboots the device,
-     * then waits and verifies the download succeeded.
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadManagerSingleReboot() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "initiateDownload", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-
-        assertTrue("Failed to initiate download properly!", testPassed);
-        mPMUtils.rebootDevice();
-        testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "verifyFileDownloadSucceeded", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-        assertTrue("Failed to verify initiated download completed properyly!", testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to initiate a download on the device, reboots the device three
-     * times (using different intervals), then waits and verifies the download succeeded.
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadManagerMultipleReboots() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "initiateDownload", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-
-        assertTrue("Failed to initiate download properly!", testPassed);
-        Thread.sleep(5000);
-
-        // Do 3 random reboots - after 13, 9, and 19 seconds
-        Log.i(LOG_TAG, "First reboot...");
-        mPMUtils.rebootDevice();
-        Thread.sleep(13000);
-        Log.i(LOG_TAG, "Second reboot...");
-        mPMUtils.rebootDevice();
-        Thread.sleep(9000);
-        Log.i(LOG_TAG, "Third reboot...");
-        mPMUtils.rebootDevice();
-        Thread.sleep(19000);
-        testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "verifyFileDownloadSucceeded", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-        assertTrue("Failed to verify initiated download completed properyly!", testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test download while WiFi is enabled/disabled multiple times
-     * during the download.
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleWiFiEnableDisable() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleWiFiEnableDisable",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test switching on/off both airplane mode and WiFi
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleSwitching() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleSwitching",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test switching on/off airplane mode multiple times
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleAirplaneModeEnableDisable() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleAirplaneModeEnableDisable",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test 15 concurrent downloads of 5,000,000-byte files
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleSimultaneously() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleSimultaneously",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 833064e..1b69daf 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -42,6 +42,10 @@
         <group gid="net_bt" />
     </permission>
 
+    <permission name="android.permission.NET_TUNNELING" >
+        <group gid="vpn" />
+    </permission>
+
     <permission name="android.permission.INTERNET" >
         <group gid="inet" />
     </permission>
diff --git a/data/fonts/fallback_fonts-ja.xml b/data/fonts/fallback_fonts-ja.xml
index 5f9b5ed..82e3a38 100644
--- a/data/fonts/fallback_fonts-ja.xml
+++ b/data/fonts/fallback_fonts-ja.xml
@@ -34,7 +34,12 @@
 <familyset>
     <family>
         <fileset>
-            <file>DroidNaskh-Regular-SystemUI.ttf</file>
+            <file variant="elegant">DroidNaskh-Regular.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file variant="compact">DroidNaskh-Regular-SystemUI.ttf</file>
         </fileset>
     </family>
     <family>
@@ -91,11 +96,6 @@
     </family>
     <family>
         <fileset>
-            <file>Lohit-Telugu.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
             <file>AndroidEmoji.ttf</file>
         </fileset>
     </family>
@@ -109,4 +109,13 @@
             <file>DroidSansFallback.ttf</file>
         </fileset>
     </family>
+    <!--
+        Fonts below this point have problematic glyphs and should not be moved
+        higher in the fallback list until those glyphs have been fixed.
+    -->
+    <family>
+        <fileset>
+            <file>Lohit-Telugu.ttf</file> <!-- masks U+FFBC-10007 -->
+        </fileset>
+    </family>
 </familyset>
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 5f7017e..758adb5 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -34,7 +34,12 @@
 <familyset>
     <family>
         <fileset>
-            <file>DroidNaskh-Regular-SystemUI.ttf</file>
+            <file variant="elegant">DroidNaskh-Regular.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file variant="compact">DroidNaskh-Regular-SystemUI.ttf</file>
         </fileset>
     </family>
     <family>
@@ -91,11 +96,6 @@
     </family>
     <family>
         <fileset>
-            <file>Lohit-Telugu.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
             <file>AndroidEmoji.ttf</file>
         </fileset>
     </family>
@@ -109,4 +109,13 @@
             <file>MTLmr3m.ttf</file>
         </fileset>
     </family>
+    <!--
+        Fonts below this point have problematic glyphs and should not be moved
+        higher in the fallback list until those glyphs have been fixed.
+    -->
+    <family>
+        <fileset>
+            <file>Lohit-Telugu.ttf</file> <!-- masks U+FFBC-10007 -->
+        </fileset>
+    </family>
 </familyset>
diff --git a/docs/html/guide/google/gcm/adv.jd b/docs/html/guide/google/gcm/adv.jd
index 39e946e..5cb433f 100644
--- a/docs/html/guide/google/gcm/adv.jd
+++ b/docs/html/guide/google/gcm/adv.jd
@@ -203,7 +203,7 @@
 <p>GCM allows a maximum of 4 different collapse keys to be used by the GCM server at any given time. In other words, the GCM server can simultaneously store 4 different send-to-sync messages, each with a different collapse key. If you exceed this number GCM will only keep 4 collapse keys, with no guarantees about which ones they will be.</p>
 
 <h3 id="payload">Messages with payload</h3>
-<p>Unlike a send-to-sync message, every &quot;message with payload&quot; (non-collapsible message) is delivered. The payload the message contains can be up to 4K. For example, here is a JSON-formatted message in an IM application in which spectators are discussing a sporting event:</p>
+<p>Unlike a send-to-sync message, every &quot;message with payload&quot; (non-collapsible message) is delivered. The payload the message contains can be up to 4kb. For example, here is a JSON-formatted message in an IM application in which spectators are discussing a sporting event:</p>
 
 <pre class="prettyprint pretty-json">{
   "registration_id" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index 79edb9f..1b95520 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -651,8 +651,8 @@
   <tr>
     <td><code>data</code></td>
     <td>A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be
-included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>
-There is no limit on the number of key/value pairs, though there is a limit on the total size of the message. Optional.</td>
+included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. 
+There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). Note that the values <em>must be enclosed by strings</em>. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Optional.</td>
   </tr>
   <tr>
     <td><code>delay_while_idle</code></td>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c726d0e..c91c2f1 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -27,7 +27,6 @@
 import java.nio.ShortBuffer;
 
 public final class Bitmap implements Parcelable {
-
     /**
      * Indicates that the bitmap was created for an unknown pixel density.
      *
@@ -64,7 +63,7 @@
     private boolean mRecycled;
 
     // Package-scoped for fast access.
-    /*package*/ int mDensity = sDefaultDensity = getDefaultDensity();
+    int mDensity = sDefaultDensity = getDefaultDensity();
 
     private static volatile Matrix sScaleMatrix;
 
@@ -78,8 +77,8 @@
     public static void setDefaultDensity(int density) {
         sDefaultDensity = density;
     }
-    
-    /*package*/ static int getDefaultDensity() {
+
+    static int getDefaultDensity() {
         if (sDefaultDensity >= 0) {
             return sDefaultDensity;
         }
@@ -95,7 +94,7 @@
 
         This can be called from JNI code.
     */
-    /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
             int density) {
         this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
     }
@@ -108,7 +107,7 @@
 
         This can be called from JNI code.
     */
-    /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
             int[] layoutBounds, int density) {
         if (nativeBitmap == 0) {
             throw new RuntimeException("internal error: native bitmap is 0");
@@ -347,11 +346,15 @@
     }
 
     /**
-     * Copy the bitmap's pixels into the specified buffer (allocated by the
+     * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
      * caller). An exception is thrown if the buffer is not large enough to
      * hold all of the pixels (taking into account the number of bytes per
      * pixel) or if the Buffer subclass is not one of the support types
-     * (ByteBuffer, ShortBuffer, IntBuffer).
+     * (ByteBuffer, ShortBuffer, IntBuffer).</p>
+     * <p>The content of the bitmap is copied into the buffer as-is. This means
+     * that if this bitmap stores its pixels pre-multiplied
+     * (see {@link #isPremultiplied()}, the values in the buffer will also be
+     * pre-multiplied.</p>
      */
     public void copyPixelsToBuffer(Buffer dst) {
         int elements = dst.remaining();
@@ -382,10 +385,10 @@
     }
 
     /**
-     * Copy the pixels from the buffer, beginning at the current position,
+     * <p>Copy the pixels from the buffer, beginning at the current position,
      * overwriting the bitmap's pixels. The data in the buffer is not changed
      * in any way (unlike setPixels(), which converts from unpremultipled 32bit
-     * to whatever the bitmap's native format is.
+     * to whatever the bitmap's native format is.</p>
      */
     public void copyPixelsFromBuffer(Buffer src) {
         checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
@@ -402,7 +405,7 @@
             throw new RuntimeException("unsupported Buffer subclass");
         }
 
-        long bufferBytes = (long)elements << shift;
+        long bufferBytes = (long) elements << shift;
         long bitmapBytes = getByteCount();
 
         if (bufferBytes < bitmapBytes) {
@@ -780,6 +783,25 @@
         return mIsMutable;
     }
 
+    /**
+     * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
+     * When a pixel is pre-multiplied, the RGB components have been multiplied by
+     * the alpha component. For instance, if the original color is a 50%
+     * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is 
+     * <code>(128, 128, 0, 0)</code>.</p>
+     * 
+     * <p>This method always returns false if {@link #getConfig()} is
+     * {@link Bitmap.Config#ALPHA_8} or {@link Bitmap.Config#RGB_565}.</p>
+     * 
+     * @return true if the underlying pixels have been pre-multiplied, false
+     *         otherwise
+     */
+    public final boolean isPremultiplied() {
+        final Config config = getConfig();
+        //noinspection deprecation
+        return config == Config.ARGB_8888 || config == Config.ARGB_4444;
+    }
+
     /** Returns the bitmap's width */
     public final int getWidth() {
         return mWidth == -1 ? mWidth = nativeWidth(mNativeBitmap) : mWidth;
@@ -926,7 +948,7 @@
     /**
      * Returns the {@link Color} at the specified location. Throws an exception
      * if x or y are out of bounds (negative or >= to the width or height
-     * respectively).
+     * respectively). The returned color is a non-premultiplied ARGB value.
      *
      * @param x    The x coordinate (0...width-1) of the pixel to return
      * @param y    The y coordinate (0...height-1) of the pixel to return
@@ -944,6 +966,7 @@
      * a packed int representing a {@link Color}. The stride parameter allows
      * the caller to allow for gaps in the returned pixels array between
      * rows. For normal packed results, just pass width for the stride value.
+     * The returned colors are non-premultiplied ARGB values.
      *
      * @param pixels   The array to receive the bitmap's colors
      * @param offset   The first index to write into pixels[]
@@ -955,6 +978,7 @@
      *                 the bitmap
      * @param width    The number of pixels to read from each row
      * @param height   The number of rows to read
+     *
      * @throws IllegalArgumentException if x, y, width, height exceed the
      *         bounds of the bitmap, or if abs(stride) < width.
      * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
@@ -974,6 +998,7 @@
     /**
      * Shared code to check for illegal arguments passed to getPixel()
      * or setPixel()
+     * 
      * @param x x coordinate of the pixel
      * @param y y coordinate of the pixel
      */
@@ -1029,12 +1054,14 @@
     }
 
     /**
-     * Write the specified {@link Color} into the bitmap (assuming it is
-     * mutable) at the x,y coordinate.
+     * <p>Write the specified {@link Color} into the bitmap (assuming it is
+     * mutable) at the x,y coordinate. The color must be a
+     * non-premultiplied ARGB value.</p>
      *
      * @param x     The x coordinate of the pixel to replace (0...width-1)
      * @param y     The y coordinate of the pixel to replace (0...height-1)
-     * @param color The {@link Color} to write into the bitmap
+     * @param color The ARGB color to write into the bitmap
+     *
      * @throws IllegalStateException if the bitmap is not mutable
      * @throws IllegalArgumentException if x, y are outside of the bitmap's
      *         bounds.
@@ -1049,8 +1076,9 @@
     }
 
     /**
-     * Replace pixels in the bitmap with the colors in the array. Each element
-     * in the array is a packed int prepresenting a {@link Color}
+     * <p>Replace pixels in the bitmap with the colors in the array. Each element
+     * in the array is a packed int prepresenting a non-premultiplied ARGB
+     * {@link Color}.</p>
      *
      * @param pixels   The colors to write to the bitmap
      * @param offset   The index of the first color to read from pixels[]
@@ -1063,6 +1091,7 @@
      *                 the bitmap.
      * @param width    The number of colors to copy from pixels[] per row
      * @param height   The number of rows to write to the bitmap
+     *
      * @throws IllegalStateException if the bitmap is not mutable
      * @throws IllegalArgumentException if x, y, width, height are outside of
      *         the bitmap's bounds.
@@ -1070,7 +1099,7 @@
      *         to receive the specified number of pixels.
      */
     public void setPixels(int[] pixels, int offset, int stride,
-                          int x, int y, int width, int height) {
+            int x, int y, int width, int height) {
         checkRecycled("Can't call setPixels() on a recycled bitmap");
         if (!isMutable()) {
             throw new IllegalStateException();
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 5094df18..381e65b 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -19,6 +19,7 @@
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.TypedValue;
 
 import java.io.BufferedInputStream;
@@ -303,6 +304,7 @@
             /*  do nothing.
                 If the exception happened on open, bm will be null.
             */
+            Log.e("BitmapFactory", "Unable to decode stream: " + e);
         } finally {
             if (stream != null) {
                 try {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f9b8a5f..f68f9dc 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1055,7 +1055,6 @@
      * Get the text Locale.
      *
      * @return the paint's Locale used for drawing text, never null.
-     * @hide
      */
     public Locale getTextLocale() {
         return mLocale;
@@ -1086,7 +1085,6 @@
      * job in certain ambiguous cases
      *
      * @param locale the paint's locale value for drawing text, must not be null.
-     * @hide
      */
     public void setTextLocale(Locale locale) {
         if (locale == null) {
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 87421b1..e82ccd4 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -385,7 +385,7 @@
             Shader shader = state.mPaint.getShader();
             if (shader == null) {
                 if (mApplyGravity) {
-                    final int layoutDirection = getResolvedLayoutDirectionSelf();
+                    final int layoutDirection = getLayoutDirection();
                     Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
                             getBounds(), mDstRect, layoutDirection);
                     mApplyGravity = false;
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index c41dd07..bade9b4 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -209,7 +209,7 @@
         if ((mClipState.mOrientation & VERTICAL) != 0) {
             h -= (h - ih) * (10000 - level) / 10000;
         }
-        final int layoutDirection = getResolvedLayoutDirectionSelf();
+        final int layoutDirection = getLayoutDirection();
         Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 785582c..07bcbdc 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -124,6 +124,8 @@
     private WeakReference<Callback> mCallback = null;
     private boolean mVisible = true;
 
+    private int mLayoutDirection;
+
     /**
      * Draw in its bounds (set via setBounds) respecting optional effects such
      * as alpha (set via setAlpha) and color filter (set via setColorFilter).
@@ -296,19 +298,6 @@
     }
 
     /**
-     * Implement this interface if you want to create an drawable that is RTL aware
-     * @hide
-     */
-    public static interface Callback2 extends Callback {
-        /**
-         * A Drawable can call this to get the resolved layout direction of the <var>who</var>.
-         *
-         * @param who The drawable being queried.
-         */
-        public int getResolvedLayoutDirection(Drawable who);
-    }
-
-    /**
      * Bind a {@link Callback} object to this Drawable.  Required for clients
      * that want to support animated drawables.
      *
@@ -385,15 +374,27 @@
     }
 
     /**
-     * Get the resolved layout direction of this Drawable.
-     * @hide
+     * Returns the resolved layout direction for this Drawable.
+     *
+     * @return One of {@link View#LAYOUT_DIRECTION_LTR},
+     *   {@link View#LAYOUT_DIRECTION_RTL}
      */
-    public int getResolvedLayoutDirectionSelf() {
-        final Callback callback = getCallback();
-        if (callback == null || !(callback instanceof Callback2)) {
-            return View.LAYOUT_DIRECTION_LTR;
+    public int getLayoutDirection() {
+        return mLayoutDirection;
+    }
+
+    /**
+     * Set the layout direction for this drawable. Should be a resolved direction as the
+     * Drawable as no capacity to do the resolution on his own.
+     *
+     * @param layoutDirection One of {@link View#LAYOUT_DIRECTION_LTR},
+     *   {@link View#LAYOUT_DIRECTION_RTL},
+     *
+     */
+    public void setLayoutDirection(int layoutDirection) {
+        if (getLayoutDirection() != layoutDirection) {
+            mLayoutDirection = layoutDirection;
         }
-        return ((Callback2) callback).getResolvedLayoutDirection(this);
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index ccad250..bd2b2f0 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -221,7 +221,7 @@
             final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
             h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
         }
-        final int layoutDirection = getResolvedLayoutDirectionSelf();
+        final int layoutDirection = getLayoutDirection();
         Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
index acc5bd8..39abd4f 100644
--- a/graphics/java/android/renderscript/Matrix2f.java
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*2 + j];
+    public float get(int x, int y) {
+        return mMat[x*2 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*2 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*2 + y] = v;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 253506d..66f2c81 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*3 + j];
+    public float get(int x, int y) {
+        return mMat[x*3 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*3 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*3 + y] = v;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/graphics/java/android/renderscript/Matrix4f.java
index adc1806..a85d464 100644
--- a/graphics/java/android/renderscript/Matrix4f.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*4 + j];
+    public float get(int x, int y) {
+        return mMat[x*4 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*4 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*4 + y] = v;
     }
 
     /**
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 3d5d1a9..8c8ff4d 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -489,7 +489,7 @@
 static void
 nAllocationSetSurface(JNIEnv *_env, jobject _this, RsContext con, RsAllocation alloc, jobject sur)
 {
-    LOG_API("nAllocationSetSurfaceTexture, con(%p), alloc(%p), surface(%p)",
+    LOG_API("nAllocationSetSurface, con(%p), alloc(%p), surface(%p)",
             con, alloc, (Surface *)sur);
 
     sp<Surface> s;
diff --git a/libs/androidfw/tests/ObbFile_test.cpp b/libs/androidfw/tests/ObbFile_test.cpp
index 09d4d7d..2c9f650 100644
--- a/libs/androidfw/tests/ObbFile_test.cpp
+++ b/libs/androidfw/tests/ObbFile_test.cpp
@@ -22,6 +22,8 @@
 
 #include <gtest/gtest.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <fcntl.h>
 #include <string.h>
 
@@ -43,7 +45,7 @@
         mFileName = new char[totalLen];
         snprintf(mFileName, totalLen, "%s%s", mExternalStorage, TEST_FILENAME);
 
-        int fd = ::open(mFileName, O_CREAT | O_TRUNC);
+        int fd = ::open(mFileName, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
         if (fd < 0) {
             FAIL() << "Couldn't create " << mFileName << " for tests";
         }
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 5ec3983..a54c188 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -40,12 +40,19 @@
 		external/skia/include/utils
 
 	LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DGL_GLEXT_PROTOTYPES
-	LOCAL_CFLAGS += -fvisibility=hidden
 	LOCAL_MODULE_CLASS := SHARED_LIBRARIES
 	LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui
 	LOCAL_MODULE := libhwui
 	LOCAL_MODULE_TAGS := optional
-	
+
+	ifndef HWUI_COMPILE_SYMBOLS
+		LOCAL_CFLAGS += -fvisibility=hidden
+	endif
+
+	ifdef HWUI_COMPILE_FOR_PERF
+		LOCAL_CFLAGS += -fno-omit-frame-pointer -marm -mapcs
+	endif
+
 	include $(BUILD_SHARED_LIBRARY)
 
     include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f210820..258ced0 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -49,6 +49,7 @@
 
 Caches::Caches(): Singleton<Caches>(), mInitialized(false) {
     init();
+    initFont();
     initExtensions();
     initConstraints();
 
@@ -74,6 +75,8 @@
 
     mTexCoordsArrayEnabled = false;
 
+    glDisable(GL_SCISSOR_TEST);
+    scissorEnabled = false;
     mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
 
     glActiveTexture(gTextureUnits[0]);
@@ -89,6 +92,10 @@
     mInitialized = true;
 }
 
+void Caches::initFont() {
+    fontRenderer = GammaFontRenderer::createRenderer();
+}
+
 void Caches::initExtensions() {
     if (extensions.hasDebugMarker()) {
         eventMark = glInsertEventMarkerEXT;
@@ -169,8 +176,8 @@
             arcShapeCache.getSize(), arcShapeCache.getMaxSize());
     log.appendFormat("  TextDropShadowCache  %8d / %8d\n", dropShadowCache.getSize(),
             dropShadowCache.getMaxSize());
-    for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
-        const uint32_t size = fontRenderer.getFontRendererSize(i);
+    for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
+        const uint32_t size = fontRenderer->getFontRendererSize(i);
         log.appendFormat("  FontRenderer %d       %8d / %8d\n", i, size, size);
     }
     log.appendFormat("Other:\n");
@@ -190,8 +197,8 @@
     total += ovalShapeCache.getSize();
     total += rectShapeCache.getSize();
     total += arcShapeCache.getSize();
-    for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
-        total += fontRenderer.getFontRendererSize(i);
+    for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
+        total += fontRenderer->getFontRendererSize(i);
     }
 
     log.appendFormat("Total memory usage:\n");
@@ -244,10 +251,10 @@
             patchCache.clear();
             dropShadowCache.clear();
             gradientCache.clear();
-            fontRenderer.clear();
+            fontRenderer->clear();
             // fall through
         case kFlushMode_Moderate:
-            fontRenderer.flush();
+            fontRenderer->flush();
             textureCache.flush();
             pathCache.clear();
             roundRectShapeCache.clear();
@@ -351,14 +358,45 @@
     }
 }
 
-void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
-    if (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight) {
+bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
+    if (scissorEnabled && (x != mScissorX || y != mScissorY ||
+            width != mScissorWidth || height != mScissorHeight)) {
+
         glScissor(x, y, width, height);
 
         mScissorX = x;
         mScissorY = y;
         mScissorWidth = width;
         mScissorHeight = height;
+
+        return true;
+    }
+    return false;
+}
+
+bool Caches::enableScissor() {
+    if (!scissorEnabled) {
+        glEnable(GL_SCISSOR_TEST);
+        scissorEnabled = true;
+        return true;
+    }
+    return false;
+}
+
+bool Caches::disableScissor() {
+    if (scissorEnabled) {
+        glDisable(GL_SCISSOR_TEST);
+        scissorEnabled = false;
+        return true;
+    }
+    return false;
+}
+
+void Caches::setScissorEnabled(bool enabled) {
+    if (scissorEnabled != enabled) {
+        if (enabled) glEnable(GL_SCISSOR_TEST);
+        else glDisable(GL_SCISSOR_TEST);
+        scissorEnabled = enabled;
     }
 }
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 58361c9..4cbac41 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -197,13 +197,17 @@
     /**
      * Sets the scissor for the current surface.
      */
-    void setScissor(GLint x, GLint y, GLint width, GLint height);
+    bool setScissor(GLint x, GLint y, GLint width, GLint height);
 
     /**
      * Resets the scissor state.
      */
     void resetScissor();
 
+    bool enableScissor();
+    bool disableScissor();
+    void setScissorEnabled(bool enabled);
+
     /**
      * Returns the mesh used to draw regions. Calling this method will
      * bind a VBO of type GL_ELEMENT_ARRAY_BUFFER that contains the
@@ -221,6 +225,7 @@
     GLenum lastSrcMode;
     GLenum lastDstMode;
     Program* currentProgram;
+    bool scissorEnabled;
 
     // VBO to draw with
     GLuint meshBuffer;
@@ -244,9 +249,10 @@
     PatchCache patchCache;
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
-    GammaFontRenderer fontRenderer;
     ResourceCache resourceCache;
 
+    GammaFontRenderer* fontRenderer;
+
     // Debug methods
     PFNGLINSERTEVENTMARKEREXTPROC eventMark;
     PFNGLPUSHGROUPMARKEREXTPROC startMark;
@@ -256,6 +262,7 @@
     PFNGLGETOBJECTLABELEXTPROC getLabel;
 
 private:
+    void initFont();
     void initExtensions();
     void initConstraints();
 
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 55a860e..6795ac3 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -68,6 +68,9 @@
 // Turn on to dump display list state
 #define DEBUG_DISPLAY_LIST 0
 
+// Turn on to insert an event marker for each display list op
+#define DEBUG_DISPLAY_LIST_OPS_AS_EVENTS 0
+
 #if DEBUG_INIT
     #define INIT_LOGD(...) ALOGD(__VA_ARGS__)
 #else
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0c89014..7161c58 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -61,9 +61,9 @@
     "DrawPath",
     "DrawLines",
     "DrawPoints",
-    "DrawText",
     "DrawTextOnPath",
     "DrawPosText",
+    "DrawGeneralText",
     "ResetShader",
     "SetupShader",
     "ResetColorFilter",
@@ -486,7 +486,8 @@
                 float top = getFloat();
                 float right = getFloat();
                 float bottom = getFloat();
-                SkPaint* paint = getPaint(renderer);
+                int alpha = getInt();
+                SkXfermode::Mode mode = (SkXfermode::Mode) getInt();
                 ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", (char*) indent, OP_NAMES[op],
                         left, top, right, bottom);
             }
@@ -571,17 +572,6 @@
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
             break;
-            case DrawText: {
-                getText(&text);
-                int32_t count = getInt();
-                float x = getFloat();
-                float y = getFloat();
-                SkPaint* paint = getPaint(renderer);
-                float length = getFloat();
-                ALOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
-                        text.text(), text.length(), count, x, y, paint, length);
-            }
-            break;
             case DrawTextOnPath: {
                 getText(&text);
                 int32_t count = getInt();
@@ -602,6 +592,17 @@
                 ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
                         text.text(), text.length(), count, paint);
             }
+            break;
+            case DrawGeneralText: {
+                getText(&text);
+                int count = getInt();
+                int positionsCount = 0;
+                float* positions = getFloats(positionsCount);
+                SkPaint* paint = getPaint(renderer);
+                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
+                        text.text(), text.length(), count, paint);
+            }
+            break;
             case ResetShader: {
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
@@ -851,11 +852,13 @@
 #endif
 
     renderer.startMark(mName.string());
+
     int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     DISPLAY_LIST_LOGD("%s%s %d %d", indent, "Save",
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
     setViewProperties(renderer, level);
-    if (renderer.quickReject(0, 0, mWidth, mHeight)) {
+
+    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
         DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
         renderer.restoreToCount(restoreTo);
         renderer.endMark();
@@ -864,6 +867,7 @@
 
     DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
     int saveCount = renderer.getSaveCount() - 1;
+
     while (!mReader.eof()) {
         int op = mReader.readInt();
         if (op & OP_MAY_BE_SKIPPED_MASK) {
@@ -879,6 +883,10 @@
         }
         logBuffer.writeCommand(level, op);
 
+#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
+        Caches::getInstance().eventMark(strlen(OP_NAMES[op]), OP_NAMES[op]);
+#endif
+
         switch (op) {
             case DrawGLFunction: {
                 Functor *functor = (Functor *) getInt();
@@ -1089,11 +1097,14 @@
                 float top = getFloat();
                 float right = getFloat();
                 float bottom = getFloat();
-                SkPaint* paint = getPaint(renderer);
+
+                int alpha = getInt();
+                SkXfermode::Mode mode = (SkXfermode::Mode) getInt();
 
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 drawGlStatus |= renderer.drawPatch(bitmap, xDivs, yDivs, colors,
-                        xDivsCount, yDivsCount, numColors, left, top, right, bottom, paint);
+                        xDivsCount, yDivsCount, numColors, left, top, right, bottom,
+                        alpha, mode);
             }
             break;
             case DrawColor: {
@@ -1185,19 +1196,6 @@
                 drawGlStatus |= renderer.drawPoints(points, count, paint);
             }
             break;
-            case DrawText: {
-                getText(&text);
-                int32_t count = getInt();
-                float x = getFloat();
-                float y = getFloat();
-                SkPaint* paint = getPaint(renderer);
-                float length = getFloat();
-                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
-                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
-                drawGlStatus |= renderer.drawText(text.text(), text.length(), count, x, y,
-                        paint, length);
-            }
-            break;
             case DrawTextOnPath: {
                 getText(&text);
                 int32_t count = getInt();
@@ -1223,6 +1221,21 @@
                         positions, paint);
             }
             break;
+            case DrawGeneralText: {
+                getText(&text);
+                int32_t count = getInt();
+                float x = getFloat();
+                float y = getFloat();
+                int32_t positionsCount = 0;
+                float* positions = getFloats(positionsCount);
+                SkPaint* paint = getPaint(renderer);
+                float length = getFloat();
+                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
+                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
+                drawGlStatus |= renderer.drawGeneralText(text.text(), text.length(), count,
+                        x, y, positions, paint, length);
+            }
+            break;
             case ResetShader: {
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 renderer.resetShader();
@@ -1570,6 +1583,10 @@
 status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs,
         const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
         int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint) {
+    int alpha;
+    SkXfermode::Mode mode;
+    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+
     const bool reject = quickReject(left, top, right, bottom);
     uint32_t* location = addOp(DisplayList::DrawPatch, reject);
     addBitmap(bitmap);
@@ -1577,7 +1594,8 @@
     addInts(yDivs, height);
     addUInts(colors, numColors);
     addBounds(left, top, right, bottom);
-    addPaint(paint);
+    addInt(alpha);
+    addInt(mode);
     addSkip(location);
     return DrawGlInfo::kStatusDone;
 }
@@ -1668,37 +1686,6 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, SkPaint* paint, float length) {
-    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
-
-    // TODO: We should probably make a copy of the paint instead of modifying
-    //       it; modifying the paint will change its generationID the first
-    //       time, which might impact caches. More investigation needed to
-    //       see if it matters.
-    //       If we make a copy, then drawTextDecorations() should *not* make
-    //       its own copy as it does right now.
-    // Beware: this needs Glyph encoding (already done on the Paint constructor)
-    paint->setAntiAlias(true);
-    if (length < 0.0f) length = paint->measureText(text, bytesCount);
-
-    bool reject = false;
-    if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
-        SkPaint::FontMetrics metrics;
-        paint->getFontMetrics(&metrics, 0.0f);
-        reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
-    }
-
-    uint32_t* location = addOp(DisplayList::DrawText, reject);
-    addText(text, bytesCount);
-    addInt(count);
-    addPoint(x, y);
-    addPaint(paint);
-    addFloat(length);
-    addSkip(location);
-    return DrawGlInfo::kStatusDone;
-}
-
 status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
         SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
@@ -1725,6 +1712,39 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawGeneralText(const char* text, int bytesCount, int count,
+        float x, float y, const float* positions, SkPaint* paint, float length) {
+    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+
+    // TODO: We should probably make a copy of the paint instead of modifying
+    //       it; modifying the paint will change its generationID the first
+    //       time, which might impact caches. More investigation needed to
+    //       see if it matters.
+    //       If we make a copy, then drawTextDecorations() should *not* make
+    //       its own copy as it does right now.
+    // Beware: this needs Glyph encoding (already done on the Paint constructor)
+    paint->setAntiAlias(true);
+    if (length < 0.0f) length = paint->measureText(text, bytesCount);
+
+    bool reject = false;
+    if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
+        SkPaint::FontMetrics metrics;
+        paint->getFontMetrics(&metrics, 0.0f);
+        reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
+    }
+
+    uint32_t* location = addOp(DisplayList::DrawGeneralText, reject);
+    addText(text, bytesCount);
+    addInt(count);
+    addFloat(x);
+    addFloat(y);
+    addFloats(positions, count * 2);
+    addPaint(paint);
+    addFloat(length);
+    addSkip(location);
+    return DrawGlInfo::kStatusDone;
+}
+
 void DisplayListRenderer::resetShader() {
     addOp(DisplayList::ResetShader);
 }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 6b4c6b2..f3041dd 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -103,9 +103,9 @@
         DrawPath,
         DrawLines,
         DrawPoints,
-        DrawText,
         DrawTextOnPath,
         DrawPosText,
+        DrawGeneralText,
         ResetShader,
         SetupShader,
         ResetColorFilter,
@@ -599,12 +599,12 @@
     virtual status_t drawPath(SkPath* path, SkPaint* paint);
     virtual status_t drawLines(float* points, int count, SkPaint* paint);
     virtual status_t drawPoints(float* points, int count, SkPaint* paint);
-    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            SkPaint* paint, float length = -1.0f);
     virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
             float hOffset, float vOffset, SkPaint* paint);
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
             const float* positions, SkPaint* paint);
+    virtual status_t drawGeneralText(const char* text, int bytesCount, int count,
+            float x, float y, const float* positions, SkPaint* paint, float length);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 6b174d6..fb945a8 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -39,9 +39,6 @@
     #define EXT_LOGD(...)
 #endif
 
-// Vendor strings
-#define VENDOR_IMG "Imagination Technologies"
-
 ///////////////////////////////////////////////////////////////////////////////
 // Classes
 ///////////////////////////////////////////////////////////////////////////////
@@ -69,10 +66,6 @@
         mHasDebugMarker = hasExtension("GL_EXT_debug_marker");
         mHasDebugLabel = hasExtension("GL_EXT_debug_label");
 
-        const char* vendor = (const char*) glGetString(GL_VENDOR);
-        EXT_LOGD("Vendor: %s", vendor);
-        mNeedsHighpTexCoords = strcmp(vendor, VENDOR_IMG) == 0;
-
         // We don't need to copy the string, the OpenGL ES spec
         // guarantees the result of glGetString to point to a
         // static string as long as our OpenGL context is valid
@@ -81,7 +74,6 @@
 
     inline bool hasNPot() const { return mHasNPot; }
     inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
-    inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; }
     inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; }
     inline bool hasDebugMarker() const { return mHasDebugMarker; }
     inline bool hasDebugLabel() const { return mHasDebugLabel; }
@@ -101,7 +93,6 @@
     const char* mExtensions;
 
     bool mHasNPot;
-    bool mNeedsHighpTexCoords;
     bool mHasFramebufferFetch;
     bool mHasDiscardFramebuffer;
     bool mHasDebugMarker;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 0d6e62a..7f0ed73 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -288,13 +288,13 @@
 }
 
 void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-        int numGlyphs, Rect *bounds) {
+        int numGlyphs, Rect *bounds, const float* positions) {
     if (bounds == NULL) {
         ALOGE("No return rectangle provided to measure text");
         return;
     }
     bounds->set(1e6, -1e6, -1e6, 1e6);
-    render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL);
+    render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
 }
 
 void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
@@ -677,10 +677,19 @@
     unsigned int stride = glyph.rowBytes();
 
     uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
-    for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
-        for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
-            uint8_t tempCol = bitmapBuffer[bY * stride + bX];
-            cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
+    if (mGammaTable) {
+        for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+            for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
+                uint8_t tempCol = bitmapBuffer[bY * stride + bX];
+                cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
+            }
+        }
+    } else {
+        for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+            for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
+                uint8_t tempCol = bitmapBuffer[bY * stride + bX];
+                cacheBuffer[cacheY * cacheWidth + cacheX] = tempCol;
+            }
         }
     }
 
@@ -688,8 +697,7 @@
 }
 
 CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool allocate) {
-    uint8_t* textureMemory = NULL;
-    CacheTexture* cacheTexture = new CacheTexture(textureMemory, width, height);
+    CacheTexture* cacheTexture = new CacheTexture(width, height);
 
     if (allocate) {
         allocateTextureMemory(cacheTexture);
@@ -999,7 +1007,7 @@
 }
 
 FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
-        uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) {
+        uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
     checkInit();
 
     if (!mCurrentFont) {
@@ -1017,7 +1025,7 @@
     mBounds = NULL;
 
     Rect bounds;
-    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
+    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);
 
     uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
     uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
@@ -1031,7 +1039,7 @@
     int penY = radius - bounds.bottom;
 
     mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
-            dataBuffer, paddedWidth, paddedHeight);
+            Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions);
     blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
 
     DropShadow image;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 2ab680e..9ed6932 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -61,9 +61,8 @@
 
 class CacheTexture {
 public:
-    CacheTexture() { }
-    CacheTexture(uint8_t* texture, uint16_t width, uint16_t height) :
-            mTexture(texture), mTextureId(0), mWidth(width), mHeight(height),
+    CacheTexture(uint16_t width, uint16_t height) :
+            mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
             mLinearFiltering(false) { }
     ~CacheTexture() {
         if (mTexture) {
@@ -185,7 +184,7 @@
             uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
 
     void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-            int numGlyphs, Rect *bounds);
+            int numGlyphs, Rect *bounds, const float* positions);
 
     Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
             uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
@@ -274,7 +273,7 @@
     // After renderDropShadow returns, the called owns the memory in DropShadow.image
     // and is responsible for releasing it when it's done with it
     DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
-            uint32_t len, int numGlyphs, uint32_t radius);
+            uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
 
     GLuint getTexture(bool linearFiltering = false) {
         checkInit();
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 1be957f..bd0a4b3 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -24,20 +24,46 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
+// Utils
 ///////////////////////////////////////////////////////////////////////////////
 
-GammaFontRenderer::GammaFontRenderer() {
-    INIT_LOGD("Creating gamma font renderer");
+static int luminance(const SkPaint* paint) {
+    uint32_t c = paint->getColor();
+    const int r = (c >> 16) & 0xFF;
+    const int g = (c >>  8) & 0xFF;
+    const int b = (c      ) & 0xFF;
+    return (r * 2 + g * 5 + b) >> 3;
+}
 
+///////////////////////////////////////////////////////////////////////////////
+// Base class GammaFontRenderer
+///////////////////////////////////////////////////////////////////////////////
+
+GammaFontRenderer* GammaFontRenderer::createRenderer() {
+    // Choose the best renderer
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) {
+        if (!strcasecmp(property, "lookup")) {
+            return new LookupGammaFontRenderer();
+        } else if (!strcasecmp(property, "shader")) {
+            return new ShaderGammaFontRenderer(false);
+        } else if (!strcasecmp(property, "shader3")) {
+            return new ShaderGammaFontRenderer(true);
+        }
+    }
+
+    return new Lookup3GammaFontRenderer();
+}
+
+GammaFontRenderer::GammaFontRenderer() {
     // Get the renderer properties
     char property[PROPERTY_VALUE_MAX];
 
     // Get the gamma
-    float gamma = DEFAULT_TEXT_GAMMA;
+    mGamma = DEFAULT_TEXT_GAMMA;
     if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
         INIT_LOGD("  Setting text gamma to %s", property);
-        gamma = atof(property);
+        mGamma = atof(property);
     } else {
         INIT_LOGD("  Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
     }
@@ -61,18 +87,82 @@
         INIT_LOGD("  Using default white black gamma threshold of %d",
                 DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
     }
+}
+
+GammaFontRenderer::~GammaFontRenderer() {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Shader-based renderer
+///////////////////////////////////////////////////////////////////////////////
+
+ShaderGammaFontRenderer::ShaderGammaFontRenderer(bool multiGamma): GammaFontRenderer() {
+    INIT_LOGD("Creating shader gamma font renderer");
+    mRenderer = NULL;
+    mMultiGamma = multiGamma;
+}
+
+void ShaderGammaFontRenderer::describe(ProgramDescription& description,
+        const SkPaint* paint) const {
+    if (paint->getShader() == NULL) {
+        if (mMultiGamma) {
+            const int l = luminance(paint);
+
+            if (l <= mBlackThreshold) {
+                description.hasGammaCorrection = true;
+                description.gamma = mGamma;
+            } else if (l >= mWhiteThreshold) {
+                description.hasGammaCorrection = true;
+                description.gamma = 1.0f / mGamma;
+            }
+        } else {
+            description.hasGammaCorrection = true;
+            description.gamma = 1.0f / mGamma;
+        }
+    }
+}
+
+void ShaderGammaFontRenderer::setupProgram(ProgramDescription& description,
+        Program* program) const {
+    if (description.hasGammaCorrection) {
+        glUniform1f(program->getUniform("gamma"), description.gamma);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Lookup-based renderer
+///////////////////////////////////////////////////////////////////////////////
+
+LookupGammaFontRenderer::LookupGammaFontRenderer(): GammaFontRenderer() {
+    INIT_LOGD("Creating lookup gamma font renderer");
 
     // Compute the gamma tables
-    const float blackGamma = gamma;
-    const float whiteGamma = 1.0f / gamma;
+    const float gamma = 1.0f / mGamma;
 
     for (uint32_t i = 0; i <= 255; i++) {
-        mGammaTable[i] = i;
+        mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f));
+    }
 
+    mRenderer = NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Lookup-based renderer, using 3 different correction tables
+///////////////////////////////////////////////////////////////////////////////
+
+Lookup3GammaFontRenderer::Lookup3GammaFontRenderer(): GammaFontRenderer() {
+    INIT_LOGD("Creating lookup3 gamma font renderer");
+
+    // Compute the gamma tables
+    const float blackGamma = mGamma;
+    const float whiteGamma = 1.0f / mGamma;
+
+    for (uint32_t i = 0; i <= 255; i++) {
         const float v = i / 255.0f;
         const float black = pow(v, blackGamma);
         const float white = pow(v, whiteGamma);
 
+        mGammaTable[i] = i;
         mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
         mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
     }
@@ -81,20 +171,20 @@
     memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
 }
 
-GammaFontRenderer::~GammaFontRenderer() {
+Lookup3GammaFontRenderer::~Lookup3GammaFontRenderer() {
     for (int i = 0; i < kGammaCount; i++) {
         delete mRenderers[i];
     }
 }
 
-void GammaFontRenderer::clear() {
+void Lookup3GammaFontRenderer::clear() {
     for (int i = 0; i < kGammaCount; i++) {
         delete mRenderers[i];
         mRenderers[i] = NULL;
     }
 }
 
-void GammaFontRenderer::flush() {
+void Lookup3GammaFontRenderer::flush() {
     int count = 0;
     int min = -1;
     uint32_t minCount = UINT_MAX;
@@ -122,7 +212,7 @@
     }
 }
 
-FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) {
+FontRenderer* Lookup3GammaFontRenderer::getRenderer(Gamma gamma) {
     FontRenderer* renderer = mRenderers[gamma];
     if (!renderer) {
         renderer = new FontRenderer();
@@ -133,17 +223,13 @@
     return renderer;
 }
 
-FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
+FontRenderer& Lookup3GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
     if (paint->getShader() == NULL) {
-        uint32_t c = paint->getColor();
-        const int r = (c >> 16) & 0xFF;
-        const int g = (c >>  8) & 0xFF;
-        const int b = (c      ) & 0xFF;
-        const int luminance = (r * 2 + g * 5 + b) >> 3;
+        const int l = luminance(paint);
 
-        if (luminance <= mBlackThreshold) {
+        if (l <= mBlackThreshold) {
             return *getRenderer(kGammaBlack);
-        } else if (luminance >= mWhiteThreshold) {
+        } else if (l >= mWhiteThreshold) {
             return *getRenderer(kGammaWhite);
         }
     }
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 99f08f0..c4a50be 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -20,20 +20,131 @@
 #include <SkPaint.h>
 
 #include "FontRenderer.h"
+#include "Program.h"
 
 namespace android {
 namespace uirenderer {
 
-struct GammaFontRenderer {
-    GammaFontRenderer();
-    ~GammaFontRenderer();
+class GammaFontRenderer {
+public:
+    virtual ~GammaFontRenderer();
 
-    enum Gamma {
-        kGammaDefault = 0,
-        kGammaBlack = 1,
-        kGammaWhite = 2,
-        kGammaCount = 3
-    };
+    virtual void clear() = 0;
+    virtual void flush() = 0;
+
+    virtual FontRenderer& getFontRenderer(const SkPaint* paint) = 0;
+
+    virtual uint32_t getFontRendererCount() const = 0;
+    virtual uint32_t getFontRendererSize(uint32_t fontRenderer) const = 0;
+
+    virtual void describe(ProgramDescription& description, const SkPaint* paint) const = 0;
+    virtual void setupProgram(ProgramDescription& description, Program* program) const = 0;
+
+    static GammaFontRenderer* createRenderer();
+
+protected:
+    GammaFontRenderer();
+
+    int mBlackThreshold;
+    int mWhiteThreshold;
+
+    float mGamma;
+};
+
+class ShaderGammaFontRenderer: public GammaFontRenderer {
+public:
+    ~ShaderGammaFontRenderer() {
+        delete mRenderer;
+    }
+
+    void clear() {
+        delete mRenderer;
+        mRenderer = NULL;
+    }
+
+    void flush() {
+        if (mRenderer) {
+            mRenderer->flushLargeCaches();
+        }
+    }
+
+    FontRenderer& getFontRenderer(const SkPaint* paint) {
+        if (!mRenderer) {
+            mRenderer = new FontRenderer;
+        }
+        return *mRenderer;
+    }
+
+    uint32_t getFontRendererCount() const {
+        return 1;
+    }
+
+    uint32_t getFontRendererSize(uint32_t fontRenderer) const {
+        return mRenderer ? mRenderer->getCacheSize() : 0;
+    }
+
+    void describe(ProgramDescription& description, const SkPaint* paint) const;
+    void setupProgram(ProgramDescription& description, Program* program) const;
+
+private:
+    ShaderGammaFontRenderer(bool multiGamma);
+
+    FontRenderer* mRenderer;
+    bool mMultiGamma;
+
+    friend class GammaFontRenderer;
+};
+
+class LookupGammaFontRenderer: public GammaFontRenderer {
+public:
+    ~LookupGammaFontRenderer() {
+        delete mRenderer;
+    }
+
+    void clear() {
+        delete mRenderer;
+    }
+
+    void flush() {
+        if (mRenderer) {
+            mRenderer->flushLargeCaches();
+        }
+    }
+
+    FontRenderer& getFontRenderer(const SkPaint* paint) {
+        if (!mRenderer) {
+            mRenderer = new FontRenderer;
+            mRenderer->setGammaTable(&mGammaTable[0]);
+        }
+        return *mRenderer;
+    }
+
+    uint32_t getFontRendererCount() const {
+        return 1;
+    }
+
+    uint32_t getFontRendererSize(uint32_t fontRenderer) const {
+        return mRenderer ? mRenderer->getCacheSize() : 0;
+    }
+
+    void describe(ProgramDescription& description, const SkPaint* paint) const {
+    }
+
+    void setupProgram(ProgramDescription& description, Program* program) const {
+    }
+
+private:
+    LookupGammaFontRenderer();
+
+    FontRenderer* mRenderer;
+    uint8_t mGammaTable[256];
+
+    friend class GammaFontRenderer;
+};
+
+class Lookup3GammaFontRenderer: public GammaFontRenderer {
+public:
+    ~Lookup3GammaFontRenderer();
 
     void clear();
     void flush();
@@ -53,16 +164,30 @@
         return renderer->getCacheSize();
     }
 
+    void describe(ProgramDescription& description, const SkPaint* paint) const {
+    }
+
+    void setupProgram(ProgramDescription& description, Program* program) const {
+    }
+
 private:
+    Lookup3GammaFontRenderer();
+
+    enum Gamma {
+        kGammaDefault = 0,
+        kGammaBlack = 1,
+        kGammaWhite = 2,
+        kGammaCount = 3
+    };
+
     FontRenderer* getRenderer(Gamma gamma);
 
     uint32_t mRenderersUsageCount[kGammaCount];
     FontRenderer* mRenderers[kGammaCount];
 
-    int mBlackThreshold;
-    int mWhiteThreshold;
-
     uint8_t mGammaTable[256 * kGammaCount];
+
+    friend class GammaFontRenderer;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 3678788..7026eead 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include <GLES2/gl2.h>
-
 #include <SkCanvas.h>
 #include <SkGradientShader.h>
 
@@ -45,6 +43,8 @@
         INIT_LOGD("  Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE);
     }
 
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+
     mCache.setOnEntryRemovedListener(this);
 }
 
@@ -116,8 +116,11 @@
 
 Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
         uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) {
+    int width = 256 * (count - 1);
+    width = width < mMaxTextureSize ? width : mMaxTextureSize;
+
     SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1);
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, 4);
     bitmap.allocPixels();
     bitmap.eraseColor(0);
 
@@ -134,7 +137,7 @@
     p.setStyle(SkPaint::kStrokeAndFill_Style);
     p.setShader(localShader)->unref();
 
-    canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p);
+    canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 4.0f, p);
 
     // Asume the cache is always big enough
     const uint32_t size = bitmap.rowBytes() * bitmap.height();
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index ac34684..59515a1 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HWUI_GRADIENT_CACHE_H
 #define ANDROID_HWUI_GRADIENT_CACHE_H
 
+#include <GLES2/gl2.h>
+
 #include <SkShader.h>
 
 #include <utils/Mutex.h>
@@ -152,6 +154,8 @@
     uint32_t mSize;
     uint32_t mMaxSize;
 
+    GLint mMaxTextureSize;
+
     Vector<SkShader*> mGarbage;
     mutable Mutex mLock;
 }; // class GradientCache
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 65f8c7c..41a5f0d 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -233,9 +233,8 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-    glDisable(GL_SCISSOR_TEST);
+    caches.disableScissor();
     glClear(GL_COLOR_BUFFER_BIT);
-    glEnable(GL_SCISSOR_TEST);
 
     glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
 
@@ -431,7 +430,7 @@
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
                     bitmap->width(), bitmap->height(), !layer->isBlend());
 
-            glDisable(GL_SCISSOR_TEST);
+            caches.disableScissor();
             renderer.translate(0.0f, bitmap->height());
             renderer.scale(1.0f, -1.0f);
 
@@ -460,8 +459,6 @@
         }
 
 error:
-        glEnable(GL_SCISSOR_TEST);
-
 #if DEBUG_OPENGL
         if (error != GL_NO_ERROR) {
             ALOGD("GL error while copying layer into bitmap = 0x%x", error);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 8f3a0a3..531aa5b 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -61,12 +61,13 @@
             bool isOpaque, GLenum renderTarget, float* transform);
     ANDROID_API static void destroyLayer(Layer* layer);
     ANDROID_API static void destroyLayerDeferred(Layer* layer);
-    ANDROID_API static void flushLayer(Layer* layer);
     ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
 
 private:
     void generateMesh();
 
+    static void flushLayer(Layer* layer);
+
     Layer* mLayer;
 }; // class LayerRenderer
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9a90bfd..07281cc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -45,8 +45,7 @@
 #define RAD_TO_DEG (180.0f / 3.14159265f)
 #define MIN_ANGLE 0.001f
 
-// TODO: This should be set in properties
-#define ALPHA_THRESHOLD (0x7f / PANEL_BIT_DEPTH)
+#define ALPHA_THRESHOLD 0
 
 #define FILTER(paint) (paint && paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
 
@@ -158,7 +157,6 @@
     mFirstSnapshot->viewport.set(0, 0, width, height);
 
     glDisable(GL_DITHER);
-    glEnable(GL_SCISSOR_TEST);
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
     glEnableVertexAttribArray(Program::kBindingPosition);
@@ -182,6 +180,7 @@
     syncState();
 
     if (!opaque) {
+        mCaches.enableScissor();
         mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
         glClear(GL_COLOR_BUFFER_BIT);
         return DrawGlInfo::kStatusDrew;
@@ -251,7 +250,7 @@
     glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
-    glEnable(GL_SCISSOR_TEST);
+    mCaches.enableScissor();
     mCaches.resetScissor();
     dirtyClip();
 
@@ -314,6 +313,7 @@
     interrupt();
     detachFunctor(functor);
 
+    mCaches.enableScissor();
     if (mDirtyClip) {
         setScissorFromClip();
     }
@@ -449,7 +449,7 @@
 
 int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
         int alpha, int flags) {
-    if (alpha >= 255 - ALPHA_THRESHOLD) {
+    if (alpha >= 255) {
         return saveLayer(left, top, right, bottom, NULL, flags);
     } else {
         SkPaint paint;
@@ -652,6 +652,7 @@
 #endif
 
     // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
+    mCaches.enableScissor();
     mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
             clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
     glClear(GL_COLOR_BUFFER_BIT);
@@ -982,7 +983,7 @@
         // The list contains bounds that have already been clipped
         // against their initial clip rect, and the current clip
         // is likely different so we need to disable clipping here
-        glDisable(GL_SCISSOR_TEST);
+        bool scissorChanged = mCaches.disableScissor();
 
         Vertex mesh[count * 6];
         Vertex* vertex = mesh;
@@ -1010,7 +1011,7 @@
 
         glDrawArrays(GL_TRIANGLES, 0, count * 6);
 
-        glEnable(GL_SCISSOR_TEST);
+        if (scissorChanged) mCaches.enableScissor();
     } else {
         for (uint32_t i = 0; i < count; i++) {
             delete mLayers.itemAt(i);
@@ -1067,16 +1068,31 @@
     Rect clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
 
-    mCaches.setScissor(clip.left, mSnapshot->height - clip.bottom,
-            clip.getWidth(), clip.getHeight());
-
-    mDirtyClip = false;
+    if (mCaches.setScissor(clip.left, mSnapshot->height - clip.bottom,
+            clip.getWidth(), clip.getHeight())) {
+        mDirtyClip = false;
+    }
 }
 
 const Rect& OpenGLRenderer::getClipBounds() {
     return mSnapshot->getLocalClip();
 }
 
+bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom) {
+    if (mSnapshot->isIgnored()) {
+        return true;
+    }
+
+    Rect r(left, top, right, bottom);
+    mSnapshot->transform->mapRect(r);
+    r.snapToPixelBoundaries();
+
+    Rect clipRect(*mSnapshot->clipRect);
+    clipRect.snapToPixelBoundaries();
+
+    return !clipRect.intersects(r);
+}
+
 bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
     if (mSnapshot->isIgnored()) {
         return true;
@@ -1089,7 +1105,12 @@
     Rect clipRect(*mSnapshot->clipRect);
     clipRect.snapToPixelBoundaries();
 
-    return !clipRect.intersects(r);
+    bool rejected = !clipRect.intersects(r);
+    if (!isDeferred() && !rejected) {
+        mCaches.setScissorEnabled(!clipRect.contains(r));
+    }
+
+    return rejected;
 }
 
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
@@ -1109,6 +1130,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void OpenGLRenderer::setupDraw(bool clear) {
+    // TODO: It would be best if we could do this before quickReject()
+    //       changes the scissor test state
     if (clear) clearLayerRegions();
     if (mDirtyClip) {
         setScissorFromClip();
@@ -1171,6 +1194,10 @@
     mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
 }
 
+void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) {
+    mCaches.fontRenderer->describe(mDescription, paint);
+}
+
 void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
     mColorA = a;
     mColorR = r;
@@ -1298,6 +1325,10 @@
     }
 }
 
+void OpenGLRenderer::setupDrawTextGammaUniforms() {
+    mCaches.fontRenderer->setupProgram(mDescription, mCaches.currentProgram);
+}
+
 void OpenGLRenderer::setupDrawSimpleMesh() {
     bool force = mCaches.bindMeshBuffer();
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
@@ -1674,10 +1705,23 @@
 status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
         const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
         float left, float top, float right, float bottom, SkPaint* paint) {
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndModeDirect(paint, &alpha, &mode);
+
+    return drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
+            left, top, right, bottom, alpha, mode);
+}
+
+status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
+        const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
+        float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) {
     if (quickReject(left, top, right, bottom)) {
         return DrawGlInfo::kStatusDone;
     }
 
+    alpha *= mSnapshot->alpha;
+
     mCaches.activeTexture(0);
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return DrawGlInfo::kStatusDone;
@@ -1685,10 +1729,6 @@
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
     texture->setFilter(GL_LINEAR, true);
 
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
     const Patch* mesh = mCaches.patchCache.get(bitmap->width(), bitmap->height(),
             right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors);
 
@@ -1743,6 +1783,7 @@
         int color, SkXfermode::Mode mode) {
     float inverseScaleX = 1.0f;
     float inverseScaleY = 1.0f;
+
     // The quad that we use needs to account for scaling.
     if (CC_UNLIKELY(!mSnapshot->transform->isPureTranslate())) {
         Matrix4 *mat = mSnapshot->transform;
@@ -1758,24 +1799,6 @@
         inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
     }
 
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawAALine();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
-    setupDrawColorFilter();
-    setupDrawShader();
-    setupDrawBlending(true, mode);
-    setupDrawProgram();
-    setupDrawModelViewIdentity(true);
-    setupDrawColorUniforms();
-    setupDrawColorFilterUniforms();
-    setupDrawShaderIdentityUniforms();
-
-    AAVertex rects[4];
-    AAVertex* aaVertices = &rects[0];
-    void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
-    void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
-
     float boundarySizeX = .5 * inverseScaleX;
     float boundarySizeY = .5 * inverseScaleY;
 
@@ -1785,32 +1808,51 @@
     top -= boundarySizeY;
     bottom += boundarySizeY;
 
-    float width = right - left;
-    float height = bottom - top;
-
-    int widthSlot;
-    int lengthSlot;
-
-    float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
-    float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
-    setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
-            boundaryWidthProportion, widthSlot, lengthSlot);
-
-    int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
-    int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
-    glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
-    glUniform1f(inverseBoundaryLengthSlot, (1.0f / boundaryHeightProportion));
-
     if (!quickReject(left, top, right, bottom)) {
+        setupDraw();
+        setupDrawNoTexture();
+        setupDrawAALine();
+        setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+        setupDrawColorFilter();
+        setupDrawShader();
+        setupDrawBlending(true, mode);
+        setupDrawProgram();
+        setupDrawModelViewIdentity(true);
+        setupDrawColorUniforms();
+        setupDrawColorFilterUniforms();
+        setupDrawShaderIdentityUniforms();
+
+        AAVertex rects[4];
+        AAVertex* aaVertices = &rects[0];
+        void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
+        void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
+
+        int widthSlot;
+        int lengthSlot;
+
+        float width = right - left;
+        float height = bottom - top;
+
+        float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
+        float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
+        setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
+                boundaryWidthProportion, widthSlot, lengthSlot);
+
+        int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
+        int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
+        glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
+        glUniform1f(inverseBoundaryLengthSlot, (1.0f / boundaryHeightProportion));
+
         AAVertex::set(aaVertices++, left, bottom, 1, 1);
         AAVertex::set(aaVertices++, left, top, 1, 0);
         AAVertex::set(aaVertices++, right, bottom, 0, 1);
         AAVertex::set(aaVertices++, right, top, 0, 0);
         dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    }
 
-    finishDrawAALine(widthSlot, lengthSlot);
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+        finishDrawAALine(widthSlot, lengthSlot);
+    }
 }
 
 /**
@@ -1882,6 +1924,9 @@
     }
 
     getAlphaAndMode(paint, &alpha, &mode);
+
+    mCaches.enableScissor();
+
     setupDraw();
     setupDrawNoTexture();
     if (isAA) {
@@ -2012,7 +2057,7 @@
         const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
         const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
 
-        if (!quickReject(left, top, right, bottom)) {
+        if (!quickRejectNoScissor(left, top, right, bottom)) {
             if (!isAA) {
                 if (prevVertex != NULL) {
                     // Issue two repeat vertices to create degenerate triangles to bridge
@@ -2117,6 +2162,10 @@
     TextureVertex pointsData[verticesCount];
     TextureVertex* vertex = &pointsData[0];
 
+    // TODO: We should optimize this method to not generate vertices for points
+    // that lie outside of the clip.
+    mCaches.enableScissor();
+
     setupDraw();
     setupDrawNoTexture();
     setupDrawPoint(strokeWidth);
@@ -2254,6 +2303,44 @@
     return DrawGlInfo::kStatusDrew;
 }
 
+void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+        const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+        float x, float y) {
+    mCaches.activeTexture(0);
+
+    // NOTE: The drop shadow will not perform gamma correction
+    //       if shader-based correction is enabled
+    mCaches.dropShadowCache.setFontRenderer(fontRenderer);
+    const ShadowTexture* shadow = mCaches.dropShadowCache.get(
+            paint, text, bytesCount, count, mShadowRadius, positions);
+    const AutoTexture autoCleanup(shadow);
+
+    const float sx = x - shadow->left + mShadowDx;
+    const float sy = y - shadow->top + mShadowDy;
+
+    const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
+    int shadowColor = mShadowColor;
+    if (mShader) {
+        shadowColor = 0xffffffff;
+    }
+
+    setupDraw();
+    setupDrawWithTexture(true);
+    setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+    setupDrawColorFilter();
+    setupDrawShader();
+    setupDrawBlending(true, mode);
+    setupDrawProgram();
+    setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
+    setupDrawTexture(shadow->id);
+    setupDrawPureColorUniforms();
+    setupDrawColorFilterUniforms();
+    setupDrawShaderUniforms();
+    setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
+
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+}
+
 status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
         const float* positions, SkPaint* paint) {
     if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
@@ -2274,7 +2361,7 @@
         y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
     }
 
-    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
@@ -2282,6 +2369,11 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
+    if (CC_UNLIKELY(mHasShadow)) {
+        drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
+                0.0f, 0.0f);
+    }
+
     // Pick the appropriate texture filtering
     bool linearFilter = mSnapshot->transform->changesBounds();
     if (pureTranslate && !linearFilter) {
@@ -2290,6 +2382,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2302,6 +2395,7 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms(pureTranslate);
+    setupDrawTextGammaUniforms();
 
     const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
@@ -2327,8 +2421,8 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, SkPaint* paint, float length) {
+status_t OpenGLRenderer::drawGeneralText(const char* text, int bytesCount, int count,
+        float x, float y, const float* positions, SkPaint* paint, float length) {
     if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
             (paint->getAlpha() * mSnapshot->alpha == 0 && paint->getXfermode() == NULL)) {
         return DrawGlInfo::kStatusDone;
@@ -2361,10 +2455,11 @@
     }
 
 #if DEBUG_GLYPHS
-    ALOGD("OpenGLRenderer drawText() with FontID=%d", SkTypeface::UniqueID(paint->getTypeface()));
+    ALOGD("OpenGLRenderer drawGeneralText() with FontID=%d",
+            SkTypeface::UniqueID(paint->getTypeface()));
 #endif
 
-    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
@@ -2373,37 +2468,8 @@
     getAlphaAndMode(paint, &alpha, &mode);
 
     if (CC_UNLIKELY(mHasShadow)) {
-        mCaches.activeTexture(0);
-
-        mCaches.dropShadowCache.setFontRenderer(fontRenderer);
-        const ShadowTexture* shadow = mCaches.dropShadowCache.get(
-                paint, text, bytesCount, count, mShadowRadius);
-        const AutoTexture autoCleanup(shadow);
-
-        const float sx = oldX - shadow->left + mShadowDx;
-        const float sy = oldY - shadow->top + mShadowDy;
-
-        const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
-        int shadowColor = mShadowColor;
-        if (mShader) {
-            shadowColor = 0xffffffff;
-        }
-
-        setupDraw();
-        setupDrawWithTexture(true);
-        setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
-        setupDrawColorFilter();
-        setupDrawShader();
-        setupDrawBlending(true, mode);
-        setupDrawProgram();
-        setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
-        setupDrawTexture(shadow->id);
-        setupDrawPureColorUniforms();
-        setupDrawColorFilterUniforms();
-        setupDrawShaderUniforms();
-        setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
-
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+        drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
+                oldX, oldY);
     }
 
     // Pick the appropriate texture filtering
@@ -2415,6 +2481,7 @@
     // The font renderer will always use texture unit 0
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2429,6 +2496,7 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms(pureTranslate);
+    setupDrawTextGammaUniforms();
 
     const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
@@ -2439,8 +2507,16 @@
     const bool hasActiveLayer = false;
 #endif
 
-    if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
-            hasActiveLayer ? &bounds : NULL)) {
+    bool status;
+    if (positions != NULL) {
+        status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
+            positions, hasActiveLayer ? &bounds : NULL);
+    } else {
+        // TODO: would it be okay to call renderPosText with null positions?
+        status = fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
+            hasActiveLayer ? &bounds : NULL);
+    }
+    if (status) {
 #if RENDER_LAYERS_AS_REGIONS
         if (hasActiveLayer) {
             if (!pureTranslate) {
@@ -2463,7 +2539,7 @@
         return DrawGlInfo::kStatusDone;
     }
 
-    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
@@ -2473,6 +2549,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2485,6 +2562,7 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms(false);
+    setupDrawTextGammaUniforms();
 
     const Rect* clip = &mSnapshot->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
@@ -2918,30 +2996,9 @@
 }
 
 void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
-    if (paint) {
-        *mode = getXfermode(paint->getXfermode());
-
-        // Skia draws using the color's alpha channel if < 255
-        // Otherwise, it uses the paint's alpha
-        int color = paint->getColor();
-        *alpha = (color >> 24) & 0xFF;
-        if (*alpha == 255) {
-            *alpha = paint->getAlpha();
-        }
-    } else {
-        *mode = SkXfermode::kSrcOver_Mode;
-        *alpha = 255;
-    }
+    getAlphaAndModeDirect(paint, alpha,  mode);
     *alpha *= mSnapshot->alpha;
 }
 
-SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) {
-    SkXfermode::Mode resultMode;
-    if (!SkXfermode::AsMode(mode, &resultMode)) {
-        resultMode = SkXfermode::kSrcOver_Mode;
-    }
-    return resultMode;
-}
-
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7aac87c..378fc8c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -105,6 +105,7 @@
 
     ANDROID_API const Rect& getClipBounds();
     ANDROID_API bool quickReject(float left, float top, float right, float bottom);
+    bool quickRejectNoScissor(float left, float top, float right, float bottom);
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
     virtual Rect* getClipRect();
 
@@ -123,6 +124,9 @@
     virtual status_t drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
             const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
             float left, float top, float right, float bottom, SkPaint* paint);
+    status_t drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
+            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
+            float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode);
     virtual status_t drawColor(int color, SkXfermode::Mode mode);
     virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint);
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
@@ -134,12 +138,12 @@
     virtual status_t drawPath(SkPath* path, SkPaint* paint);
     virtual status_t drawLines(float* points, int count, SkPaint* paint);
     virtual status_t drawPoints(float* points, int count, SkPaint* paint);
-    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            SkPaint* paint, float length = -1.0f);
     virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
             float hOffset, float vOffset, SkPaint* paint);
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
             const float* positions, SkPaint* paint);
+    virtual status_t drawGeneralText(const char* text, int bytesCount, int count, float x, float y,
+            const float* positions, SkPaint* paint, float length = -1.0f);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
@@ -213,6 +217,54 @@
      */
     void drawTextureLayer(Layer* layer, const Rect& rect);
 
+    /**
+     * Gets the alpha and xfermode out of a paint object. If the paint is null
+     * alpha will be 255 and the xfermode will be SRC_OVER.
+     *
+     * @param paint The paint to extract values from
+     * @param alpha Where to store the resulting alpha
+     * @param mode Where to store the resulting xfermode
+     */
+    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
+
+    /**
+     * Gets the alpha and xfermode out of a paint object. If the paint is null
+     * alpha will be 255 and the xfermode will be SRC_OVER. This method does
+     * not multiply the paint's alpha by the current snapshot's alpha.
+     *
+     * @param paint The paint to extract values from
+     * @param alpha Where to store the resulting alpha
+     * @param mode Where to store the resulting xfermode
+     */
+    static inline void getAlphaAndModeDirect(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+        if (paint) {
+            *mode = getXfermode(paint->getXfermode());
+
+            // Skia draws using the color's alpha channel if < 255
+            // Otherwise, it uses the paint's alpha
+            int color = paint->getColor();
+            *alpha = (color >> 24) & 0xFF;
+            if (*alpha == 255) {
+                *alpha = paint->getAlpha();
+            }
+        } else {
+            *mode = SkXfermode::kSrcOver_Mode;
+            *alpha = 255;
+        }
+    }
+
+    /**
+     * Safely retrieves the mode from the specified xfermode. If the specified
+     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
+     */
+    static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
+        SkXfermode::Mode resultMode;
+        if (!SkXfermode::AsMode(mode, &resultMode)) {
+            resultMode = SkXfermode::kSrcOver_Mode;
+        }
+        return resultMode;
+    }
+
 private:
     /**
      * Ensures the state of the renderer is the same as the state of
@@ -446,6 +498,24 @@
     void drawTextDecorations(const char* text, int bytesCount, float length,
             float x, float y, SkPaint* paint);
 
+   /**
+     * Draws shadow layer on text (with optional positions).
+     *
+     * @param paint The paint to draw the shadow with
+     * @param text The text to draw
+     * @param bytesCount The number of bytes in the text
+     * @param count The number of glyphs in the text
+     * @param positions The x, y positions of individual glyphs (or NULL)
+     * @param fontRenderer The font renderer object
+     * @param alpha The alpha value for drawing the shadow
+     * @param mode The xfermode for drawing the shadow
+     * @param x The x coordinate where the shadow will be drawn
+     * @param y The y coordinate where the shadow will be drawn
+     */
+    void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+            const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+            float x, float y);
+
     /**
      * Draws a path texture. Path textures are alpha8 bitmaps that need special
      * compositing to apply colors/filters/etc.
@@ -455,7 +525,7 @@
      * @param y The y coordinate where the texture will be drawn
      * @param paint The paint to draw the texture with
      */
-    void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
+     void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
 
     /**
      * Resets the texture coordinates stored in mMeshVertices. Setting the values
@@ -471,16 +541,6 @@
     void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2);
 
     /**
-     * Gets the alpha and xfermode out of a paint object. If the paint is null
-     * alpha will be 255 and the xfermode will be SRC_OVER.
-     *
-     * @param paint The paint to extract values from
-     * @param alpha Where to store the resulting alpha
-     * @param mode Where to store the resulting xfermode
-     */
-    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
-
-    /**
      * Binds the specified texture. The texture unit must have been selected
      * prior to calling this method.
      */
@@ -504,12 +564,6 @@
             bool swapSrcDst = false);
 
     /**
-     * Safely retrieves the mode from the specified xfermode. If the specified
-     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
-     */
-    inline SkXfermode::Mode getXfermode(SkXfermode* mode);
-
-    /**
      * Use the specified program with the current GL context. If the program is already
      * in use, it will not be bound again. If it is not in use, the current program is
      * marked unused and the specified program becomes used and becomes the new
@@ -537,6 +591,7 @@
     void setupDrawColor(int color, int alpha);
     void setupDrawColor(float r, float g, float b, float a);
     void setupDrawAlpha8Color(int color, int alpha);
+    void setupDrawTextGamma(const SkPaint* paint);
     void setupDrawShader();
     void setupDrawColorFilter();
     void setupDrawBlending(SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode,
@@ -561,6 +616,7 @@
     void setupDrawExternalTexture(GLuint texture);
     void setupDrawTextureTransform();
     void setupDrawTextureTransformUniforms(mat4& transform);
+    void setupDrawTextGammaUniforms();
     void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
     void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords);
     void setupDrawVertices(GLvoid* vertices);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index eb9ee7b..491767f 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -41,8 +41,8 @@
     #define PROGRAM_LOGD(...)
 #endif
 
-#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
-#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
+#define COLOR_COMPONENT_THRESHOLD 1.0f
+#define COLOR_COMPONENT_INV_THRESHOLD 0.0f
 
 #define PROGRAM_KEY_TEXTURE 0x1
 #define PROGRAM_KEY_A8_TEXTURE 0x2
@@ -77,6 +77,8 @@
 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
 
+#define PROGRAM_HAS_GAMMA_CORRECTION 40
+
 ///////////////////////////////////////////////////////////////////////////////
 // Types
 ///////////////////////////////////////////////////////////////////////////////
@@ -146,6 +148,9 @@
     bool isPoint;
     float pointSize;
 
+    bool hasGammaCorrection;
+    float gamma;
+
     /**
      * Resets this description. All fields are reset back to the default
      * values they hold after building a new instance.
@@ -180,6 +185,9 @@
 
         isPoint = false;
         pointSize = 0.0f;
+
+        hasGammaCorrection = false;
+        gamma = 2.2f;
     }
 
     /**
@@ -246,6 +254,7 @@
         if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
+        if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
         return key;
     }
 
@@ -261,7 +270,7 @@
     }
 
 private:
-    inline uint32_t getEnumForWrap(GLenum wrap) const {
+    static inline uint32_t getEnumForWrap(GLenum wrap) {
         switch (wrap) {
             case GL_CLAMP_TO_EDGE:
                 return 0;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index a7f1277..70bd1a8 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -65,25 +65,19 @@
 const char* gVS_Header_Varyings_IsAA =
         "varying float widthProportion;\n"
         "varying float lengthProportion;\n";
-const char* gVS_Header_Varyings_HasBitmap[2] = {
-        // Default precision
-        "varying vec2 outBitmapTexCoords;\n",
-        // High precision
-        "varying highp vec2 outBitmapTexCoords;\n"
-};
-const char* gVS_Header_Varyings_PointHasBitmap[2] = {
-        // Default precision
-        "varying vec2 outPointBitmapTexCoords;\n",
-        // High precision
-        "varying highp vec2 outPointBitmapTexCoords;\n"
-};
+const char* gVS_Header_Varyings_HasBitmap =
+        "varying highp vec2 outBitmapTexCoords;\n";
+const char* gVS_Header_Varyings_PointHasBitmap =
+        "varying highp vec2 outPointBitmapTexCoords;\n";
+// TODO: These values are used to sample from textures,
+//       they may need to be highp
 const char* gVS_Header_Varyings_HasGradient[3] = {
         // Linear
-        "varying vec2 linear;\n",
+        "varying highp vec2 linear;\n",
         // Circular
-        "varying vec2 circular;\n",
+        "varying highp vec2 circular;\n",
         // Sweep
-        "varying vec2 sweep;\n"
+        "varying highp vec2 sweep;\n"
 };
 const char* gVS_Main =
         "\nvoid main(void) {\n";
@@ -159,12 +153,15 @@
         // PorterDuff
         "uniform vec4 colorBlend;\n"
 };
+const char* gFS_Uniforms_Gamma =
+        "uniform float gamma;\n";
+
 const char* gFS_Main =
         "\nvoid main(void) {\n"
         "    lowp vec4 fragColor;\n";
 
 const char* gFS_Main_PointBitmapTexCoords =
-        "    vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
+        "    highp vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
         "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n";
 
 // Fast cases
@@ -184,10 +181,18 @@
         "\nvoid main(void) {\n"
         "    gl_FragColor = texture2D(sampler, outTexCoords);\n"
         "}\n\n";
+const char* gFS_Fast_SingleA8Texture_ApplyGamma =
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(sampler, outTexCoords).a, gamma));\n"
+        "}\n\n";
 const char* gFS_Fast_SingleModulateA8Texture =
         "\nvoid main(void) {\n"
         "    gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n"
         "}\n\n";
+const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = color * pow(texture2D(sampler, outTexCoords).a, gamma);\n"
+        "}\n\n";
 const char* gFS_Fast_SingleGradient =
         "\nvoid main(void) {\n"
         "    gl_FragColor = texture2D(gradientSampler, linear);\n"
@@ -202,6 +207,8 @@
         "    fragColor = color;\n";
 const char* gFS_Main_ModulateColor =
         "    fragColor *= color.a;\n";
+const char* gFS_Main_ModulateColor_ApplyGamma =
+        "    fragColor *= pow(color.a, gamma);\n";
 const char* gFS_Main_AccountForAA =
         "    if (widthProportion < boundaryWidth) {\n"
         "        fragColor *= (widthProportion * inverseBoundaryWidth);\n"
@@ -229,10 +236,10 @@
         // Linear
         "    vec4 gradientColor = texture2D(gradientSampler, linear);\n",
         // Circular
-        "    float index = length(circular);\n"
+        "    highp float index = length(circular);\n"
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
         // Sweep
-        "    float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
+        "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n"
 };
 const char* gFS_Main_FetchBitmap =
@@ -426,10 +433,9 @@
         shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
     }
     if (description.hasBitmap) {
-        int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0;
         shader.append(description.isPoint ?
-                gVS_Header_Varyings_PointHasBitmap[index] :
-                gVS_Header_Varyings_HasBitmap[index]);
+                gVS_Header_Varyings_PointHasBitmap :
+                gVS_Header_Varyings_HasBitmap);
     }
 
     // Begin the shader
@@ -488,10 +494,9 @@
         shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
     }
     if (description.hasBitmap) {
-        int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0;
         shader.append(description.isPoint ?
-                gVS_Header_Varyings_PointHasBitmap[index] :
-                gVS_Header_Varyings_HasBitmap[index]);
+                gVS_Header_Varyings_PointHasBitmap :
+                gVS_Header_Varyings_HasBitmap);
     }
 
     // Uniforms
@@ -517,6 +522,9 @@
     if (description.hasBitmap && description.isPoint) {
         shader.append(gFS_Header_Uniforms_PointHasBitmap);
     }
+    if (description.hasGammaCorrection) {
+        shader.append(gFS_Uniforms_Gamma);
+    }
 
     // Optimization for common cases
     if (!description.isAA && !blendFramebuffer &&
@@ -544,9 +552,17 @@
             fast = true;
         } else if (singleA8Texture) {
             if (!description.modulate) {
-                shader.append(gFS_Fast_SingleA8Texture);
+                if (description.hasGammaCorrection) {
+                    shader.append(gFS_Fast_SingleA8Texture_ApplyGamma);
+                } else {
+                    shader.append(gFS_Fast_SingleA8Texture);
+                }
             } else {
-                shader.append(gFS_Fast_SingleModulateA8Texture);
+                if (description.hasGammaCorrection) {
+                    shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma);
+                } else {
+                    shader.append(gFS_Fast_SingleModulateA8Texture);
+                }
             }
             fast = true;
         } else if (singleGradient) {
@@ -643,7 +659,11 @@
             }
         }
         if (description.modulate && applyModulate) {
-            shader.append(gFS_Main_ModulateColor);
+            if (description.hasGammaCorrection) {
+                shader.append(gFS_Main_ModulateColor_ApplyGamma);
+            } else {
+                shader.append(gFS_Main_ModulateColor);
+            }
         }
         // Apply the color op if needed
         shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
@@ -676,13 +696,13 @@
 }
 
 void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) {
-    shader.append("\nvec2 wrap(vec2 texCoords) {\n");
+    shader.append("\nhighp vec2 wrap(highp vec2 texCoords) {\n");
     if (wrapS == GL_MIRRORED_REPEAT) {
-        shader.append("    float xMod2 = mod(texCoords.x, 2.0);\n");
+        shader.append("    highp float xMod2 = mod(texCoords.x, 2.0);\n");
         shader.append("    if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n");
     }
     if (wrapT == GL_MIRRORED_REPEAT) {
-        shader.append("    float yMod2 = mod(texCoords.y, 2.0);\n");
+        shader.append("    highp float yMod2 = mod(texCoords.y, 2.0);\n");
         shader.append("    if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n");
     }
     shader.append("    return vec2(");
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 7854729..3f3b39a 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -73,13 +73,30 @@
 #define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width"
 #define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height"
 
-// Gamma (>= 1.0, <= 10.0)
-#define PROPERTY_TEXT_GAMMA "ro.text_gamma"
-#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "ro.text_gamma.black_threshold"
-#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "ro.text_gamma.white_threshold"
+// Indicates whether gamma correction should be applied in the shaders
+// or in lookup tables. Accepted values:
+//
+//     - "lookup3", correction based on lookup tables. Gamma correction
+//        is different for black and white text (see thresholds below)
+//
+//     - "lookup", correction based on a single lookup table
+//
+//     - "shader3", correction applied by a GLSL shader. Gamma correction
+//        is different for black and white text (see thresholds below)
+//
+//     - "shader", correction applied by a GLSL shader
+//
+// See PROPERTY_TEXT_GAMMA, PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD and
+// PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD for more control.
+#define PROPERTY_TEXT_GAMMA_METHOD "hwui.text_gamma_correction"
+#define DEFAULT_TEXT_GAMMA_METHOD "lookup"
 
-// TODO: This should be set by a system property
-#define PANEL_BIT_DEPTH 20
+// Gamma (>= 1.0, <= 10.0)
+#define PROPERTY_TEXT_GAMMA "hwui.text_gamma"
+// Luminance threshold below which black gamma correction is applied. Range: [0..255]
+#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "hwui.text_gamma.black_threshold"
+// Lumincance threshold above which white gamma correction is applied. Range: [0..255]
+#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "hwui.text_gamma.white_threshold"
 
 // Converts a number of mega-bytes into bytes
 #define MB(s) s * 1024 * 1024
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 2ca4f50..80f39ff 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -125,11 +125,11 @@
         return intersect(r.left, r.top, r.right, r.bottom);
     }
 
-    bool contains(float l, float t, float r, float b) {
+    inline bool contains(float l, float t, float r, float b) {
         return l >= left && t >= top && r <= right && b <= bottom;
     }
 
-    bool contains(const Rect& r) {
+    inline bool contains(const Rect& r) {
         return contains(r.left, r.top, r.right, r.bottom);
     }
 
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index cf5f822..2153a8b 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -48,7 +48,8 @@
 
 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL || mCache->size() == 0) {
         ref = new ResourceReference(resourceType);
         mCache->add(resource, ref);
@@ -78,7 +79,8 @@
 
 void ResourceCache::decrementRefcount(void* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
         return;
@@ -111,12 +113,13 @@
 
 void ResourceCache::recycle(SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
-    if (mCache->indexOfKey(resource) < 0) {
+    ssize_t index = mCache->indexOfKey(resource);
+    if (index < 0) {
         // not tracking this resource; just recycle the pixel data
         resource->setPixels(NULL, NULL);
         return;
     }
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ResourceReference* ref = mCache->valueAt(index);
     if (ref == NULL) {
         // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
         return;
@@ -129,7 +132,8 @@
 
 void ResourceCache::destructor(SkPath* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
@@ -146,7 +150,8 @@
 
 void ResourceCache::destructor(SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
@@ -163,7 +168,8 @@
 
 void ResourceCache::destructor(SkiaShader* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         delete resource;
@@ -177,7 +183,8 @@
 
 void ResourceCache::destructor(SkiaColorFilter* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         delete resource;
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index bef1373..93aa8a5 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -102,13 +102,13 @@
 }
 
 ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
-        int numGlyphs, uint32_t radius) {
-    ShadowText entry(paint, radius, len, text);
+        int numGlyphs, uint32_t radius, const float* positions) {
+    ShadowText entry(paint, radius, len, text, positions);
     ShadowTexture* texture = mCache.get(entry);
 
     if (!texture) {
         FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
-                len, numGlyphs, radius);
+                len, numGlyphs, radius, positions);
 
         texture = new ShadowTexture;
         texture->left = shadow.penX;
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index e2bdde1..bae0c49 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -35,8 +35,9 @@
     ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
     }
 
-    ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
-            radius(radius), len(len) {
+    ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText,
+            const float* positions):
+            radius(radius), len(len), positions(positions) {
         // TODO: Propagate this through the API, we should not cast here
         text = (const char16_t*) srcText;
 
@@ -66,11 +67,18 @@
     uint32_t italicStyle;
     uint32_t scaleX;
     const char16_t* text;
+    const float* positions;
     String16 str;
+    Vector<float> positionsCopy;
 
     void copyTextLocally() {
         str.setTo((const char16_t*) text, len >> 1);
         text = str.string();
+        if (positions != NULL) {
+            positionsCopy.clear();
+            positionsCopy.appendArray(positions, len);
+            positions = positionsCopy.array();
+        }
     }
 
     bool operator<(const ShadowText& rhs) const {
@@ -81,7 +89,12 @@
                         LTE_INT(flags) {
                             LTE_INT(italicStyle) {
                                 LTE_INT(scaleX) {
-                                    return memcmp(text, rhs.text, len) < 0;
+                                    int cmp = memcmp(text, rhs.text, len);
+                                    if (cmp < 0) return true;
+                                    if (cmp == 0 && rhs.positions != NULL) {
+                                        if (positions == NULL) return true;
+                                        return memcmp(positions, rhs.positions, len << 2) < 0;
+                                    }
                                 }
                             }
                         }
@@ -117,7 +130,7 @@
     void operator()(ShadowText& text, ShadowTexture*& texture);
 
     ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
-            int numGlyphs, uint32_t radius);
+            int numGlyphs, uint32_t radius, const float* positions);
 
     /**
      * Clears the cache. This causes all textures to be deleted.
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 2255bf2..47b7adf 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -54,7 +54,7 @@
     boolean sendExtraCommand(String provider, String command, inout Bundle extras);
 
     void addProximityAlert(double latitude, double longitude, float distance,
-        long expiration, in PendingIntent intent);
+        long expiration, in PendingIntent intent, in String packageName);
     void removeProximityAlert(in PendingIntent intent);
 
     Bundle getProviderInfo(String provider);
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index aacf857..5ad60ab 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.util.Printer;
 
 import java.text.DecimalFormat;
@@ -59,6 +60,7 @@
 
     private String mProvider;
     private long mTime = 0;
+    private long mElapsedRealtimeNano = 0;
     private double mLatitude = 0.0;
     private double mLongitude = 0.0;
     private boolean mHasAltitude = false;
@@ -84,6 +86,7 @@
 
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "mProvider=" + mProvider + " mTime=" + mTime);
+        pw.println(prefix + "mElapsedRealtimeNano=" + mElapsedRealtimeNano);
         pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
         pw.println(prefix + "mHasAltitude=" + mHasAltitude + " mAltitude=" + mAltitude);
         pw.println(prefix + "mHasSpeed=" + mHasSpeed + " mSpeed=" + mSpeed);
@@ -118,6 +121,7 @@
     public void set(Location l) {
         mProvider = l.mProvider;
         mTime = l.mTime;
+        mElapsedRealtimeNano = l.mElapsedRealtimeNano;
         mLatitude = l.mLatitude;
         mLongitude = l.mLongitude;
         mHasAltitude = l.mHasAltitude;
@@ -137,6 +141,7 @@
     public void reset() {
         mProvider = null;
         mTime = 0;
+        mElapsedRealtimeNano = 0;
         mLatitude = 0;
         mLongitude = 0;
         mHasAltitude = false;
@@ -467,23 +472,62 @@
     }
 
     /**
-     * Returns the UTC time of this fix, in milliseconds since January 1,
+     * Return the UTC time of this fix, in milliseconds since January 1,
      * 1970.
+     * <p>Note that the UTC time on a device is not monotonic: it
+     * can jump forwards or backwards unpredictably. So always use
+     * {@link #getElapsedRealtimeNano()} when calculating time deltas.
+     * <p>On the other hand, {@link #getTime()} is useful for presenting
+     * a human readable time to the user, or for carefully comparing
+     * location fixes across reboot or across devices.
+     * <p>This method will always return a valid timestamp on
+     * Locations generated by a {@link LocationProvider}.
+     *
+     * @return time of fix, in milliseconds since January 1, 1970.
      */
     public long getTime() {
         return mTime;
     }
 
     /**
-     * Sets the UTC time of this fix, in milliseconds since January 1,
+     * Set the UTC time of this fix, in milliseconds since January 1,
      * 1970.
+     *
+     * @param time UTC time of this fix, in milliseconds since January 1, 1970
      */
     public void setTime(long time) {
         mTime = time;
     }
 
     /**
-     * Returns the latitude of this fix.
+     * Return the time of this fix, in elapsed real-time since system boot.
+     * <p>This value can be reliably compared to
+     * {@link android.os.SystemClock#elapsedRealtimeNano()},
+     * to calculate the age of a fix, and to compare Location fixes, since
+     * elapsed real-time is guaranteed monotonic for each system boot, and
+     * continues to increment even when the system is in deep sleep.
+     * <p>This method will always return a valid timestamp on
+     * Locations generated by a {@link LocationProvider}.
+     *
+     * @return elapsed real-time of fix, in nanoseconds since system boot.
+     */
+    public long getElapsedRealtimeNano() {
+        return mElapsedRealtimeNano;
+    }
+
+    /**
+     * Set the time of this fix, in elapsed real-time since system boot.
+     *
+     * @param time elapsed real-time of fix, in nanoseconds since system boot.
+     */
+    public void setElapsedRealtimeNano(long time) {
+        mElapsedRealtimeNano = time;
+    }
+
+    /**
+     * Return the latitude of this fix.
+     * <p>This method will always return a valid latitude on
+     * Locations generated by a {@link LocationProvider}.
      */
     public double getLatitude() {
         return mLatitude;
@@ -497,7 +541,9 @@
     }
 
     /**
-     * Returns the longitude of this fix.
+     * Return the longitude of this fix.
+     * <p>This method will always return a valid longitude on
+     * Locations generated by a {@link LocationProvider}.
      */
     public double getLongitude() {
         return mLongitude;
@@ -619,16 +665,27 @@
     }
 
     /**
-     * Returns true if the provider is able to report accuracy information,
-     * false otherwise.  The default implementation returns false.
+     * Return true if this Location has an associated accuracy.
+     * <p>All Location objects generated by a {@link LocationProvider}
+     * will have an accuracy.
      */
     public boolean hasAccuracy() {
         return mHasAccuracy;
     }
 
     /**
-     * Returns the accuracy of the fix in meters. If hasAccuracy() is false,
-     * 0.0 is returned.
+     * Return the accuracy of this Location fix.
+     * <p>Accuracy is measured in meters, and indicates the
+     * radius of 95% confidence.
+     * In other words, there is a 95% probability that the
+     * true location is within a circle centered at the reported
+     * location, with radius of the reported accuracy.
+     * <p>This is only a measure of horizontal accuracy, and does
+     * not indicate the accuracy of bearing, velocity or altitude
+     * if those are included in this Location.
+     * <p>If {@link #hasAccuracy} is false, 0.0 is returned.
+     * <p>All Location object generated by a {@link LocationProvider}
+     * will have a valid accuracy.
      */
     public float getAccuracy() {
         return mAccuracy;
@@ -653,6 +710,37 @@
     }
 
     /**
+     * Return true if this Location object has enough data set to
+     * be considered a valid fix from a {@link LocationProvider}.
+     * @see #makeComplete
+     * @hide
+     */
+    public boolean isComplete() {
+        if (mProvider == null) return false;
+        if (!mHasAccuracy) return false;
+        if (mTime == 0) return false;
+        if (mElapsedRealtimeNano == 0) return false;
+        return true;
+    }
+
+    /**
+     * Helper to fill in incomplete fields.
+     * Only use this to assist in backwards compatibility
+     * with Location objects received from applications.
+     * @see #isComplete
+     * @hide
+     */
+    public void makeComplete() {
+        if (mProvider == null) mProvider = "?";
+        if (!mHasAccuracy) {
+            mHasAccuracy = true;
+            mAccuracy = 100.0f;
+        }
+        if (mTime == 0) mTime = System.currentTimeMillis();
+        if (mElapsedRealtimeNano == 0) mElapsedRealtimeNano = SystemClock.elapsedRealtimeNano();
+    }
+
+    /**
      * Returns additional provider-specific information about the
      * location fix as a Bundle.  The keys and values are determined
      * by the provider.  If no additional information is available,
@@ -681,6 +769,7 @@
     @Override public String toString() {
         return "Location[mProvider=" + mProvider +
             ",mTime=" + mTime +
+            ",mElapsedRealtimeNano=" + mElapsedRealtimeNano +
             ",mLatitude=" + mLatitude +
             ",mLongitude=" + mLongitude +
             ",mHasAltitude=" + mHasAltitude +
@@ -700,6 +789,7 @@
             String provider = in.readString();
             Location l = new Location(provider);
             l.mTime = in.readLong();
+            l.mElapsedRealtimeNano = in.readLong();
             l.mLatitude = in.readDouble();
             l.mLongitude = in.readDouble();
             l.mHasAltitude = in.readInt() != 0;
@@ -726,6 +816,7 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeString(mProvider);
         parcel.writeLong(mTime);
+        parcel.writeLong(mElapsedRealtimeNano);
         parcel.writeDouble(mLatitude);
         parcel.writeDouble(mLongitude);
         parcel.writeInt(mHasAltitude ? 1 : 0);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 1299574..15a2928 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -17,12 +17,15 @@
 package android.location;
 
 import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.location.DummyLocationProvider;
@@ -52,7 +55,9 @@
  */
 public class LocationManager {
     private static final String TAG = "LocationManager";
-    private ILocationManager mService;
+
+    private final Context mContext;
+    private final ILocationManager mService;
     private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
             new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
     private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
@@ -193,6 +198,7 @@
             }
         }
 
+        @Override
         public void onLocationChanged(Location location) {
             Message msg = Message.obtain();
             msg.what = TYPE_LOCATION_CHANGED;
@@ -200,6 +206,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onStatusChanged(String provider, int status, Bundle extras) {
             Message msg = Message.obtain();
             msg.what = TYPE_STATUS_CHANGED;
@@ -213,6 +220,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onProviderEnabled(String provider) {
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_ENABLED;
@@ -220,6 +228,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onProviderDisabled(String provider) {
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_DISABLED;
@@ -260,8 +269,9 @@
      * right way to create an instance of this class is using the
      * factory Context.getSystemService.
      */
-    public LocationManager(ILocationManager service) {
+    public LocationManager(Context context, ILocationManager service) {
         mService = service;
+        mContext = context;
     }
 
     private LocationProvider createProvider(String name, Bundle info) {
@@ -1086,8 +1096,8 @@
                 ", intent = " + intent);
         }
         try {
-            mService.addProximityAlert(latitude, longitude, radius,
-                                       expiration, intent);
+            mService.addProximityAlert(latitude, longitude, radius, expiration, intent,
+                    mContext.getPackageName());
         } catch (RemoteException ex) {
             Log.e(TAG, "addProximityAlert: RemoteException", ex);
         }
@@ -1212,8 +1222,11 @@
     }
 
     /**
-     * Sets a mock location for the given provider.  This location will be used in place
-     * of any actual location from the provider.
+     * Sets a mock location for the given provider.
+     * <p>This location will be used in place of any actual location from the provider.
+     * The location object must have a minimum number of fields set to be
+     * considered a valid LocationProvider Location, as per documentation
+     * on {@link Location} class.
      *
      * @param provider the provider name
      * @param loc the mock location
@@ -1222,8 +1235,20 @@
      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
      * @throws IllegalArgumentException if no provider with the given name exists
+     * @throws IllegalArgumentException if the location is incomplete
      */
     public void setTestProviderLocation(String provider, Location loc) {
+        if (!loc.isComplete()) {
+            if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
+                // for backwards compatibility, allow mock locations that are incomplete
+                Log.w(TAG, "Incomplete Location object", new Throwable());
+                loc.makeComplete();
+            } else {
+                throw new IllegalArgumentException(
+                        "Location object not complete. Missing timestamps or accuracy?");
+            }
+        }
+
         try {
             mService.setTestProviderLocation(provider, loc);
         } catch (RemoteException ex) {
@@ -1361,6 +1386,7 @@
             mNmeaBuffer = new ArrayList<Nmea>();
         }
 
+        @Override
         public void onGpsStarted() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1369,6 +1395,7 @@
             }
         }
 
+        @Override
         public void onGpsStopped() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1377,6 +1404,7 @@
             }
         }
 
+        @Override
         public void onFirstFix(int ttff) {
             if (mListener != null) {
                 mGpsStatus.setTimeToFirstFix(ttff);
@@ -1386,6 +1414,7 @@
             }
         }
 
+        @Override
         public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
                 float[] elevations, float[] azimuths, int ephemerisMask,
                 int almanacMask, int usedInFixMask) {
@@ -1401,6 +1430,7 @@
             }
         }
 
+        @Override
         public void onNmeaReceived(long timestamp, String nmea) {
             if (mNmeaListener != null) {
                 synchronized (mNmeaBuffer) {
diff --git a/location/java/com/android/internal/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java
index e7b5143..3122960 100644
--- a/location/java/com/android/internal/location/DummyLocationProvider.java
+++ b/location/java/com/android/internal/location/DummyLocationProvider.java
@@ -24,7 +24,7 @@
  * A DummyLocationProvider may be queried to determine the properties
  * of the provider whcih it shadows, but does not actually provide location
  * data.
- * 
+ *
  * {@hide}
  */
 public class DummyLocationProvider extends LocationProvider {
@@ -86,6 +86,7 @@
      * Returns true if the provider requires access to a
      * data network (e.g., the Internet), false otherwise.
      */
+    @Override
     public boolean requiresNetwork() {
         return mRequiresNetwork;
     }
@@ -95,6 +96,7 @@
      * satellite-based positioning system (e.g., GPS), false
      * otherwise.
      */
+    @Override
     public boolean requiresSatellite() {
         return mRequiresSatellite;
     }
@@ -104,6 +106,7 @@
      * cellular network (e.g., to make use of cell tower IDs), false
      * otherwise.
      */
+    @Override
     public boolean requiresCell() {
         return mRequiresCell;
     }
@@ -113,6 +116,7 @@
      * monetary charge to the user, false if use is free.  It is up to
      * each provider to give accurate information.
      */
+    @Override
     public boolean hasMonetaryCost() {
         return mHasMonetaryCost;
     }
@@ -123,6 +127,7 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
+    @Override
     public boolean supportsAltitude() {
         return mSupportsAltitude;
     }
@@ -133,6 +138,7 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
+    @Override
     public boolean supportsSpeed() {
         return mSupportsSpeed;
     }
@@ -143,6 +149,7 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
+    @Override
     public boolean supportsBearing() {
         return mSupportsBearing;
     }
@@ -153,6 +160,7 @@
      * @return the power requirement for this provider, as one of the
      * constants Criteria.POWER_REQUIREMENT_*.
      */
+    @Override
     public int getPowerRequirement() {
         return mPowerRequirement;
     }
@@ -164,6 +172,7 @@
      * @return the horizontal accuracy for this provider, as one of the
      * constants Criteria.ACCURACY_*.
      */
+    @Override
     public int getAccuracy() {
         return mAccuracy;
     }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b6e4659..b5613f3 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -49,6 +49,7 @@
     private final Context mContext;
     private long mVolumeKeyUpTime;
     private final boolean mUseMasterVolume;
+    private final boolean mUseVolumeKeySounds;
     private static String TAG = "AudioManager";
 
     /**
@@ -412,6 +413,8 @@
         mContext = context;
         mUseMasterVolume = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_useMasterVolume);
+        mUseVolumeKeySounds = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useVolumeKeySounds);
     }
 
     private static IAudioService getService()
@@ -463,6 +466,7 @@
                  * responsive to the user.
                  */
                 int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
+
                 if (mUseMasterVolume) {
                     adjustMasterVolume(
                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
@@ -502,18 +506,17 @@
                  * Play a sound. This is done on key up since we don't want the
                  * sound to play when a user holds down volume down to mute.
                  */
-                if (mUseMasterVolume) {
-                    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+                if (mUseVolumeKeySounds) {
+                    if (mUseMasterVolume) {
                         adjustMasterVolume(ADJUST_SAME, FLAG_PLAY_SOUND);
+                    } else {
+                        int flags = FLAG_PLAY_SOUND;
+                        adjustSuggestedStreamVolume(
+                                ADJUST_SAME,
+                                stream,
+                                flags);
                     }
-                } else {
-                    int flags = FLAG_PLAY_SOUND;
-                    adjustSuggestedStreamVolume(
-                            ADJUST_SAME,
-                            stream,
-                            flags);
                 }
-
                 mVolumeKeyUpTime = SystemClock.uptimeMillis();
                 break;
         }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e153dd..d2a8298 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -143,11 +143,12 @@
     private static final int MSG_REEVALUATE_REMOTE = 17;
     private static final int MSG_RCC_NEW_PLAYBACK_INFO = 18;
     private static final int MSG_RCC_NEW_VOLUME_OBS = 19;
+    private static final int MSG_SET_FORCE_BT_A2DP_USE = 20;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
-    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 20;
-    private static final int MSG_SET_A2DP_CONNECTION_STATE = 21;
+    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 21;
+    private static final int MSG_SET_A2DP_CONNECTION_STATE = 22;
     // end of messages handled under wakelock
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -381,7 +382,7 @@
     // message looper for SoundPool listener
     private Looper mSoundPoolLooper = null;
     // volume applied to sound played with playSoundEffect()
-    private static int SOUND_EFFECT_VOLUME_DB;
+    private static int sSoundEffectVolumeDb;
     // getActiveStreamType() will return STREAM_NOTIFICATION during this period after a notification
     // stopped
     private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000;
@@ -438,7 +439,7 @@
             "ro.config.vc_call_vol_steps",
            MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
 
-        SOUND_EFFECT_VOLUME_DB = context.getResources().getInteger(
+        sSoundEffectVolumeDb = context.getResources().getInteger(
                 com.android.internal.R.integer.config_soundEffectVolumeDb);
 
         mVolumePanel = new VolumePanel(context, this);
@@ -1701,7 +1702,13 @@
 
     /** @see AudioManager#setBluetoothA2dpOn() */
     public void setBluetoothA2dpOn(boolean on) {
-        setBluetoothA2dpOnInt(on);
+        synchronized (mBluetoothA2dpEnabledLock) {
+            mBluetoothA2dpEnabled = on;
+            sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
+                    AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
+                    null, 0);
+        }
     }
 
     /** @see AudioManager#isBluetoothA2dpOn() */
@@ -2875,7 +2882,7 @@
                 float volFloat;
                 // use default if volume is not specified by caller
                 if (volume < 0) {
-                    volFloat = (float)Math.pow(10, SOUND_EFFECT_VOLUME_DB/20);
+                    volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
                 } else {
                     volFloat = (float) volume / 1000.0f;
                 }
@@ -3049,6 +3056,7 @@
                     break;
 
                 case MSG_SET_FORCE_USE:
+                case MSG_SET_FORCE_BT_A2DP_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
@@ -5290,10 +5298,9 @@
     public void setBluetoothA2dpOnInt(boolean on) {
         synchronized (mBluetoothA2dpEnabledLock) {
             mBluetoothA2dpEnabled = on;
-            sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
-                    AudioSystem.FOR_MEDIA,
-                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
-                    null, 0);
+            mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
+            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
         }
     }
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index cd25865b..7693e80 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2319,6 +2319,11 @@
      */
     public static final int MEDIA_INFO_STARTED_AS_NEXT = 2;
 
+    /** The player just pushed the very first video frame for rendering.
+     * @see android.media.MediaPlayer.OnInfoListener
+     */
+    public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3;
+
     /** The video is too complex for the decoder: it can't decode frames fast
      *  enough. Possibly only the audio plays fine at this stage.
      * @see android.media.MediaPlayer.OnInfoListener
@@ -2374,6 +2379,7 @@
          * <ul>
          * <li>{@link #MEDIA_INFO_UNKNOWN}
          * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING}
+         * <li>{@link #MEDIA_INFO_VIDEO_RENDERING_START}
          * <li>{@link #MEDIA_INFO_BUFFERING_START}
          * <li>{@link #MEDIA_INFO_BUFFERING_END}
          * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 6f8b809..5cd5ff5 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -314,6 +314,7 @@
     private int mMtpObjectHandle;
 
     private final String mExternalStoragePath;
+    private final boolean mExternalIsEmulated;
 
     /** whether to use bulk inserts or individual inserts for each item */
     private static final boolean ENABLE_BULK_INSERTS = true;
@@ -392,6 +393,7 @@
         setDefaultRingtoneFileNames();
 
         mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
+        mExternalIsEmulated = Environment.isExternalStorageEmulated();
         //mClient.testGenreNameConverter();
     }
 
@@ -543,13 +545,28 @@
                         boolean music = (lowpath.indexOf(MUSIC_DIR) > 0) ||
                             (!ringtones && !notifications && !alarms && !podcasts);
 
+                        boolean isaudio = MediaFile.isAudioFileType(mFileType);
+                        boolean isvideo = MediaFile.isVideoFileType(mFileType);
+                        boolean isimage = MediaFile.isImageFileType(mFileType);
+
+                        if (isaudio || isvideo || isimage) {
+                            if (mExternalIsEmulated && path.startsWith(mExternalStoragePath)) {
+                                // try to rewrite the path to bypass the sd card fuse layer
+                                String directPath = Environment.getMediaStorageDirectory() +
+                                        path.substring(mExternalStoragePath.length());
+                                File f = new File(directPath);
+                                if (f.exists()) {
+                                    path = directPath;
+                                }
+                            }
+                        }
+
                         // we only extract metadata for audio and video files
-                        if (MediaFile.isAudioFileType(mFileType)
-                                || MediaFile.isVideoFileType(mFileType)) {
+                        if (isaudio || isvideo) {
                             processFile(path, mimeType, this);
                         }
 
-                        if (MediaFile.isImageFileType(mFileType)) {
+                        if (isimage) {
                             processImageFile(path);
                         }
 
@@ -972,7 +989,6 @@
                     }
                     values.put(FileColumns.MEDIA_TYPE, mediaType);
                 }
-
                 mMediaProvider.update(result, values, null, null);
             }
 
diff --git a/media/libstagefright/codecs/aacdec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/aacdec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/aacdec/NOTICE b/media/libstagefright/codecs/aacdec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/aacenc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/aacenc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/aacenc/NOTICE b/media/libstagefright/codecs/aacenc/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/aacenc/SampleCode/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/NOTICE b/media/libstagefright/codecs/aacenc/SampleCode/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrnb/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrnb/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/NOTICE b/media/libstagefright/codecs/amrnb/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrnb/common/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrnb/common/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/common/NOTICE b/media/libstagefright/codecs/amrnb/common/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/dec/NOTICE b/media/libstagefright/codecs/amrnb/dec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrnb/enc/NOTICE b/media/libstagefright/codecs/amrnb/enc/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrwb/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrwb/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrwb/NOTICE b/media/libstagefright/codecs/amrwb/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrwbenc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrwbenc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrwbenc/NOTICE b/media/libstagefright/codecs/amrwbenc/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/amrwbenc/SampleCode/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/NOTICE b/media/libstagefright/codecs/amrwbenc/SampleCode/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/avc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/avc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/avc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/avc/NOTICE b/media/libstagefright/codecs/avc/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/avc/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/avc/common/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/avc/common/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/avc/common/NOTICE b/media/libstagefright/codecs/avc/common/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/avc/enc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/avc/enc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/avc/enc/NOTICE b/media/libstagefright/codecs/avc/enc/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/common/NOTICE b/media/libstagefright/codecs/common/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/common/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/g711/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/g711/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/g711/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/g711/NOTICE b/media/libstagefright/codecs/g711/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/g711/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/g711/dec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/g711/dec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/g711/dec/NOTICE b/media/libstagefright/codecs/g711/dec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/m4v_h263/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/m4v_h263/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/m4v_h263/NOTICE b/media/libstagefright/codecs/m4v_h263/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/m4v_h263/dec/NOTICE b/media/libstagefright/codecs/m4v_h263/dec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/m4v_h263/enc/NOTICE b/media/libstagefright/codecs/m4v_h263/enc/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/mp3dec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/mp3dec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/mp3dec/NOTICE b/media/libstagefright/codecs/mp3dec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/on2/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/on2/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/on2/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/on2/NOTICE b/media/libstagefright/codecs/on2/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/on2/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/on2/dec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/on2/dec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/on2/dec/NOTICE b/media/libstagefright/codecs/on2/dec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/vorbis/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/vorbis/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/vorbis/NOTICE b/media/libstagefright/codecs/vorbis/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/media/libstagefright/codecs/vorbis/dec/MODULE_LICENSE_APACHE2 b/media/libstagefright/codecs/vorbis/dec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/vorbis/dec/NOTICE b/media/libstagefright/codecs/vorbis/dec/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/dec/NOTICE
@@ -0,0 +1,202 @@
+
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
new file mode 100644
index 0000000..4cdc272
--- /dev/null
+++ b/opengl/java/android/opengl/EGL14.java
@@ -0,0 +1,446 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import android.graphics.SurfaceTexture;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+
+/**
+ * EGL 1.4
+ *
+ */
+public class EGL14 {
+
+public static final int EGL_DEFAULT_DISPLAY            = 0;
+public static EGLContext EGL_NO_CONTEXT                = null;
+public static EGLDisplay EGL_NO_DISPLAY                = null;
+public static EGLSurface EGL_NO_SURFACE                = null;
+
+public static final int EGL_FALSE                          = 0;
+public static final int EGL_TRUE                           = 1;
+public static final int EGL_SUCCESS                        = 0x3000;
+public static final int EGL_NOT_INITIALIZED                = 0x3001;
+public static final int EGL_BAD_ACCESS                     = 0x3002;
+public static final int EGL_BAD_ALLOC                      = 0x3003;
+public static final int EGL_BAD_ATTRIBUTE                  = 0x3004;
+public static final int EGL_BAD_CONFIG                     = 0x3005;
+public static final int EGL_BAD_CONTEXT                    = 0x3006;
+public static final int EGL_BAD_CURRENT_SURFACE            = 0x3007;
+public static final int EGL_BAD_DISPLAY                    = 0x3008;
+public static final int EGL_BAD_MATCH                      = 0x3009;
+public static final int EGL_BAD_NATIVE_PIXMAP              = 0x300A;
+public static final int EGL_BAD_NATIVE_WINDOW              = 0x300B;
+public static final int EGL_BAD_PARAMETER                  = 0x300C;
+public static final int EGL_BAD_SURFACE                    = 0x300D;
+public static final int EGL_CONTEXT_LOST                   = 0x300E;
+public static final int EGL_BUFFER_SIZE                    = 0x3020;
+public static final int EGL_ALPHA_SIZE                     = 0x3021;
+public static final int EGL_BLUE_SIZE                      = 0x3022;
+public static final int EGL_GREEN_SIZE                     = 0x3023;
+public static final int EGL_RED_SIZE                       = 0x3024;
+public static final int EGL_DEPTH_SIZE                     = 0x3025;
+public static final int EGL_STENCIL_SIZE                   = 0x3026;
+public static final int EGL_CONFIG_CAVEAT                  = 0x3027;
+public static final int EGL_CONFIG_ID                      = 0x3028;
+public static final int EGL_LEVEL                          = 0x3029;
+public static final int EGL_MAX_PBUFFER_HEIGHT             = 0x302A;
+public static final int EGL_MAX_PBUFFER_PIXELS             = 0x302B;
+public static final int EGL_MAX_PBUFFER_WIDTH              = 0x302C;
+public static final int EGL_NATIVE_RENDERABLE              = 0x302D;
+public static final int EGL_NATIVE_VISUAL_ID               = 0x302E;
+public static final int EGL_NATIVE_VISUAL_TYPE             = 0x302F;
+public static final int EGL_SAMPLES                        = 0x3031;
+public static final int EGL_SAMPLE_BUFFERS                 = 0x3032;
+public static final int EGL_SURFACE_TYPE                   = 0x3033;
+public static final int EGL_TRANSPARENT_TYPE               = 0x3034;
+public static final int EGL_TRANSPARENT_BLUE_VALUE         = 0x3035;
+public static final int EGL_TRANSPARENT_GREEN_VALUE        = 0x3036;
+public static final int EGL_TRANSPARENT_RED_VALUE          = 0x3037;
+public static final int EGL_NONE                           = 0x3038;
+public static final int EGL_BIND_TO_TEXTURE_RGB            = 0x3039;
+public static final int EGL_BIND_TO_TEXTURE_RGBA           = 0x303A;
+public static final int EGL_MIN_SWAP_INTERVAL              = 0x303B;
+public static final int EGL_MAX_SWAP_INTERVAL              = 0x303C;
+public static final int EGL_LUMINANCE_SIZE                 = 0x303D;
+public static final int EGL_ALPHA_MASK_SIZE                = 0x303E;
+public static final int EGL_COLOR_BUFFER_TYPE              = 0x303F;
+public static final int EGL_RENDERABLE_TYPE                = 0x3040;
+public static final int EGL_MATCH_NATIVE_PIXMAP            = 0x3041;
+public static final int EGL_CONFORMANT                     = 0x3042;
+public static final int EGL_SLOW_CONFIG                    = 0x3050;
+public static final int EGL_NON_CONFORMANT_CONFIG          = 0x3051;
+public static final int EGL_TRANSPARENT_RGB                = 0x3052;
+public static final int EGL_RGB_BUFFER                     = 0x308E;
+public static final int EGL_LUMINANCE_BUFFER               = 0x308F;
+public static final int EGL_NO_TEXTURE                     = 0x305C;
+public static final int EGL_TEXTURE_RGB                    = 0x305D;
+public static final int EGL_TEXTURE_RGBA                   = 0x305E;
+public static final int EGL_TEXTURE_2D                     = 0x305F;
+public static final int EGL_PBUFFER_BIT                    = 0x0001;
+public static final int EGL_PIXMAP_BIT                     = 0x0002;
+public static final int EGL_WINDOW_BIT                     = 0x0004;
+public static final int EGL_VG_COLORSPACE_LINEAR_BIT       = 0x0020;
+public static final int EGL_VG_ALPHA_FORMAT_PRE_BIT        = 0x0040;
+public static final int EGL_MULTISAMPLE_RESOLVE_BOX_BIT    = 0x0200;
+public static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT    = 0x0400;
+public static final int EGL_OPENGL_ES_BIT                  = 0x0001;
+public static final int EGL_OPENVG_BIT                     = 0x0002;
+public static final int EGL_OPENGL_ES2_BIT                 = 0x0004;
+public static final int EGL_OPENGL_BIT                     = 0x0008;
+public static final int EGL_VENDOR                         = 0x3053;
+public static final int EGL_VERSION                        = 0x3054;
+public static final int EGL_EXTENSIONS                     = 0x3055;
+public static final int EGL_CLIENT_APIS                    = 0x308D;
+public static final int EGL_HEIGHT                         = 0x3056;
+public static final int EGL_WIDTH                          = 0x3057;
+public static final int EGL_LARGEST_PBUFFER                = 0x3058;
+public static final int EGL_TEXTURE_FORMAT                 = 0x3080;
+public static final int EGL_TEXTURE_TARGET                 = 0x3081;
+public static final int EGL_MIPMAP_TEXTURE                 = 0x3082;
+public static final int EGL_MIPMAP_LEVEL                   = 0x3083;
+public static final int EGL_RENDER_BUFFER                  = 0x3086;
+public static final int EGL_VG_COLORSPACE                  = 0x3087;
+public static final int EGL_VG_ALPHA_FORMAT                = 0x3088;
+public static final int EGL_HORIZONTAL_RESOLUTION          = 0x3090;
+public static final int EGL_VERTICAL_RESOLUTION            = 0x3091;
+public static final int EGL_PIXEL_ASPECT_RATIO             = 0x3092;
+public static final int EGL_SWAP_BEHAVIOR                  = 0x3093;
+public static final int EGL_MULTISAMPLE_RESOLVE            = 0x3099;
+public static final int EGL_BACK_BUFFER                    = 0x3084;
+public static final int EGL_SINGLE_BUFFER                  = 0x3085;
+public static final int EGL_VG_COLORSPACE_sRGB             = 0x3089;
+public static final int EGL_VG_COLORSPACE_LINEAR           = 0x308A;
+public static final int EGL_VG_ALPHA_FORMAT_NONPRE         = 0x308B;
+public static final int EGL_VG_ALPHA_FORMAT_PRE            = 0x308C;
+public static final int EGL_DISPLAY_SCALING                = 10000;
+public static final int EGL_BUFFER_PRESERVED               = 0x3094;
+public static final int EGL_BUFFER_DESTROYED               = 0x3095;
+public static final int EGL_OPENVG_IMAGE                   = 0x3096;
+public static final int EGL_CONTEXT_CLIENT_TYPE            = 0x3097;
+public static final int EGL_CONTEXT_CLIENT_VERSION         = 0x3098;
+public static final int EGL_MULTISAMPLE_RESOLVE_DEFAULT    = 0x309A;
+public static final int EGL_MULTISAMPLE_RESOLVE_BOX        = 0x309B;
+public static final int EGL_OPENGL_ES_API                  = 0x30A0;
+public static final int EGL_OPENVG_API                     = 0x30A1;
+public static final int EGL_OPENGL_API                     = 0x30A2;
+public static final int EGL_DRAW                           = 0x3059;
+public static final int EGL_READ                           = 0x305A;
+public static final int EGL_CORE_NATIVE_ENGINE             = 0x305B;
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
+    // C function EGLint eglGetError ( void )
+
+    public static native int eglGetError(
+    );
+
+    // C function EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id )
+
+    public static native EGLDisplay eglGetDisplay(
+        int display_id
+    );
+
+    // C function EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor )
+
+    public static native boolean eglInitialize(
+        EGLDisplay dpy,
+        int[] major,
+        int majorOffset,
+        int[] minor,
+        int minorOffset
+    );
+
+    // C function EGLBoolean eglTerminate ( EGLDisplay dpy )
+
+    public static native boolean eglTerminate(
+        EGLDisplay dpy
+    );
+
+    // C function const char * eglQueryString ( EGLDisplay dpy, EGLint name )
+
+    public static native String eglQueryString(
+        EGLDisplay dpy,
+        int name
+    );
+    // C function EGLBoolean eglGetConfigs ( EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config )
+
+    public static native boolean eglGetConfigs(
+        EGLDisplay dpy,
+        EGLConfig[] configs,
+        int configsOffset,
+        int config_size,
+        int[] num_config,
+        int num_configOffset
+    );
+
+    // C function EGLBoolean eglChooseConfig ( EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config )
+
+    public static native boolean eglChooseConfig(
+        EGLDisplay dpy,
+        int[] attrib_list,
+        int attrib_listOffset,
+        EGLConfig[] configs,
+        int configsOffset,
+        int config_size,
+        int[] num_config,
+        int num_configOffset
+    );
+
+    // C function EGLBoolean eglGetConfigAttrib ( EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value )
+
+    public static native boolean eglGetConfigAttrib(
+        EGLDisplay dpy,
+        EGLConfig config,
+        int attribute,
+        int[] value,
+        int offset
+    );
+
+    // C function EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list )
+
+    private static native EGLSurface _eglCreateWindowSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    );
+
+    private static native EGLSurface _eglCreateWindowSurfaceTexture(
+        EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    );
+
+    public static EGLSurface eglCreateWindowSurface(EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    ){
+        Surface sur = null;
+        if (win instanceof SurfaceView) {
+            SurfaceView surfaceView = (SurfaceView)win;
+            sur = surfaceView.getHolder().getSurface();
+        } else if (win instanceof SurfaceHolder) {
+            SurfaceHolder holder = (SurfaceHolder)win;
+            sur = holder.getSurface();
+        }
+
+        EGLSurface surface;
+        if (sur != null) {
+            surface = _eglCreateWindowSurface(dpy, config, sur, attrib_list, offset);
+        } else if (win instanceof SurfaceTexture) {
+            surface = _eglCreateWindowSurfaceTexture(dpy, config,
+                    win, attrib_list, offset);
+        } else {
+            throw new java.lang.UnsupportedOperationException(
+                "eglCreateWindowSurface() can only be called with an instance of " +
+                "SurfaceView, SurfaceTexture or SurfaceHolder at the moment, " +
+                "this will be fixed later.");
+        }
+
+        return surface;
+    }
+    // C function EGLSurface eglCreatePbufferSurface ( EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list )
+
+    public static native EGLSurface eglCreatePbufferSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLSurface eglCreatePixmapSurface ( EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list )
+
+    public static native EGLSurface eglCreatePixmapSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        int pixmap,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglDestroySurface ( EGLDisplay dpy, EGLSurface surface )
+
+    public static native boolean eglDestroySurface(
+        EGLDisplay dpy,
+        EGLSurface surface
+    );
+
+    // C function EGLBoolean eglQuerySurface ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value )
+
+    public static native boolean eglQuerySurface(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int attribute,
+        int[] value,
+        int offset
+    );
+
+    // C function EGLBoolean eglBindAPI ( EGLenum api )
+
+    public static native boolean eglBindAPI(
+        int api
+    );
+
+    // C function EGLenum eglQueryAPI ( void )
+
+    public static native int eglQueryAPI(
+    );
+
+    // C function EGLBoolean eglWaitClient ( void )
+
+    public static native boolean eglWaitClient(
+    );
+
+    // C function EGLBoolean eglReleaseThread ( void )
+
+    public static native boolean eglReleaseThread(
+    );
+
+    // C function EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list )
+
+    public static native EGLSurface eglCreatePbufferFromClientBuffer(
+        EGLDisplay dpy,
+        int buftype,
+        int buffer,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value )
+
+    public static native boolean eglSurfaceAttrib(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int attribute,
+        int value
+    );
+
+    // C function EGLBoolean eglBindTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer )
+
+    public static native boolean eglBindTexImage(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int buffer
+    );
+
+    // C function EGLBoolean eglReleaseTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer )
+
+    public static native boolean eglReleaseTexImage(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int buffer
+    );
+
+    // C function EGLBoolean eglSwapInterval ( EGLDisplay dpy, EGLint interval )
+
+    public static native boolean eglSwapInterval(
+        EGLDisplay dpy,
+        int interval
+    );
+
+    // C function EGLContext eglCreateContext ( EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list )
+
+    public static native EGLContext eglCreateContext(
+        EGLDisplay dpy,
+        EGLConfig config,
+        EGLContext share_context,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglDestroyContext ( EGLDisplay dpy, EGLContext ctx )
+
+    public static native boolean eglDestroyContext(
+        EGLDisplay dpy,
+        EGLContext ctx
+    );
+
+    // C function EGLBoolean eglMakeCurrent ( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx )
+
+    public static native boolean eglMakeCurrent(
+        EGLDisplay dpy,
+        EGLSurface draw,
+        EGLSurface read,
+        EGLContext ctx
+    );
+
+    // C function EGLContext eglGetCurrentContext ( void )
+
+    public static native EGLContext eglGetCurrentContext(
+    );
+
+    // C function EGLSurface eglGetCurrentSurface ( EGLint readdraw )
+
+    public static native EGLSurface eglGetCurrentSurface(
+        int readdraw
+    );
+
+    // C function EGLDisplay eglGetCurrentDisplay ( void )
+
+    public static native EGLDisplay eglGetCurrentDisplay(
+    );
+
+    // C function EGLBoolean eglQueryContext ( EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value )
+
+    public static native boolean eglQueryContext(
+        EGLDisplay dpy,
+        EGLContext ctx,
+        int attribute,
+        int[] value,
+        int offset
+    );
+
+    // C function EGLBoolean eglWaitGL ( void )
+
+    public static native boolean eglWaitGL(
+    );
+
+    // C function EGLBoolean eglWaitNative ( EGLint engine )
+
+    public static native boolean eglWaitNative(
+        int engine
+    );
+
+    // C function EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface )
+
+    public static native boolean eglSwapBuffers(
+        EGLDisplay dpy,
+        EGLSurface surface
+    );
+
+    // C function EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target )
+
+    public static native boolean eglCopyBuffers(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int target
+    );
+
+}
diff --git a/opengl/java/android/opengl/EGLConfig.java b/opengl/java/android/opengl/EGLConfig.java
new file mode 100644
index 0000000..d457c9f
--- /dev/null
+++ b/opengl/java/android/opengl/EGLConfig.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLConfig objects.
+ *
+ */
+public class EGLConfig extends EGLObjectHandle {
+    private EGLConfig(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLConfig that = (EGLConfig) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLContext.java b/opengl/java/android/opengl/EGLContext.java
new file mode 100644
index 0000000..41b8ef1
--- /dev/null
+++ b/opengl/java/android/opengl/EGLContext.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLContext objects.
+ *
+ */
+public class EGLContext extends EGLObjectHandle {
+    private EGLContext(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLContext that = (EGLContext) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLDisplay.java b/opengl/java/android/opengl/EGLDisplay.java
new file mode 100644
index 0000000..17d1a64
--- /dev/null
+++ b/opengl/java/android/opengl/EGLDisplay.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLDisplay objects.
+ *
+ */
+public class EGLDisplay extends EGLObjectHandle {
+    private EGLDisplay(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLDisplay that = (EGLDisplay) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLObjectHandle.java b/opengl/java/android/opengl/EGLObjectHandle.java
new file mode 100644
index 0000000..d2710de
--- /dev/null
+++ b/opengl/java/android/opengl/EGLObjectHandle.java
@@ -0,0 +1,47 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Base class for wrapped EGL objects.
+ *
+ */
+public abstract class EGLObjectHandle {
+    private final int mHandle;
+
+    protected EGLObjectHandle(int handle) {
+        mHandle = handle;
+    }
+
+    /**
+     * Returns the native handle of the wrapped EGL object. This handle can be
+     * cast to the corresponding native type on the native side.
+     *
+     * For example, EGLDisplay dpy = (EGLDisplay)handle;
+     *
+     * @return the native handle of the wrapped EGL object.
+     */
+    public int getHandle() {
+        return mHandle;
+    }
+
+    @Override
+    public int hashCode() {
+        return getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLSurface.java b/opengl/java/android/opengl/EGLSurface.java
new file mode 100644
index 0000000..65bec4f
--- /dev/null
+++ b/opengl/java/android/opengl/EGLSurface.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLSurface objects.
+ *
+ */
+public class EGLSurface extends EGLObjectHandle {
+    private EGLSurface(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLSurface that = (EGLSurface) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 635f811..2eeae62 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -829,6 +829,25 @@
         byte name
     );
 
+    // C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
+
+    public static native String glGetActiveAttrib(
+        int program,
+        int index,
+        int[] size,
+        int sizeOffset,
+        int[] type,
+        int typeOffset
+    );
+
+    // C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
+
+    public static native String glGetActiveAttrib(
+        int program,
+        int index,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type
+    );
     // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
 
     public static native void glGetActiveUniform(
@@ -856,7 +875,25 @@
         java.nio.IntBuffer type,
         byte name
     );
+    // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
 
+    public static native String glGetActiveUniform(
+        int program,
+        int index,
+        int[] size,
+        int sizeOffset,
+        int[] type,
+        int typeOffset
+    );
+
+    // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
+
+    public static native String glGetActiveUniform(
+        int program,
+        int index,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type
+    );
     // C function void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders )
 
     public static native void glGetAttachedShaders(
@@ -1105,6 +1142,11 @@
         byte source
     );
 
+    // C function void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source )
+
+    public static native String glGetShaderSource(
+        int shader
+    );
 /*
  * Copyright (C) 2009 The Android Open Source Project
  *
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 6992019..64a54c2 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -83,6 +83,8 @@
         } else if (native_window instanceof SurfaceHolder) {
             SurfaceHolder holder = (SurfaceHolder)native_window;
             sur = holder.getSurface();
+        } else if (native_window instanceof Surface) {
+            sur = (Surface) native_window;
         }
 
         int eglSurfaceId;
@@ -94,8 +96,7 @@
         } else {
             throw new java.lang.UnsupportedOperationException(
                 "eglCreateWindowSurface() can only be called with an instance of " +
-                "SurfaceView, SurfaceHolder or SurfaceTexture at the moment, " + 
-                "this will be fixed later.");
+                "Surface, SurfaceView, SurfaceHolder or SurfaceTexture at the moment.");
         }
 
         if (eglSurfaceId == 0) {
diff --git a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
index d202d74..6da7d4a 100644
--- a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
@@ -18,16 +18,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="backup_confirm_title" msgid="827563724209303345">"پشتیبان‌گیری کامل"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"بازیابی کامل"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"درخواست پشتیبان گیری کامل از تمام داده‌ها به یک رایانه دسک‌تاپ متصل داده شده است. آیا می‌خواهید این عمل انجام شود؟"\n\n"اگر شما درخواست تهیه نسخه پشتیبان را نداده‌اید، اجازه‌ ادامه عملیات را ندهید."</string>
-    <string name="allow_backup_button_label" msgid="4217228747769644068">"از داده‌های من نسخه پشتیبان تهیه شود"</string>
-    <string name="deny_backup_button_label" msgid="6009119115581097708">"نسخه پشتیبان تهیه نشود"</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"بازیابی کامل تمام داده‌ها از یک رایانه دسک تاپ متصل درخواست شده است. آیا می خواهید این اجازه را بدهید؟"\n\n"اگر خود شما درخواست بازیابی نداده‌اید، اجازه ادامه این عملیات را ندهید. با این کار همه داده‌هایی که اکنون روی دستگاه است جایگزین می‌شود!"</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"درخواست پشتیبان گیری کامل از تمام داده‌ها به یک رایانه دسک‌تاپ متصل داده شده است. آیا می‌خواهید این عمل انجام شود؟"\n\n"اگر شما درخواست تهیه نسخهٔ پشتیبان را نداده‌اید، اجازه‌ ادامه عملیات را ندهید."</string>
+    <string name="allow_backup_button_label" msgid="4217228747769644068">"از داده‌های من نسخهٔ پشتیبان تهیه شود"</string>
+    <string name="deny_backup_button_label" msgid="6009119115581097708">"نسخهٔ پشتیبان تهیه نشود"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"بازیابی کامل تمام داده‌ها از یک رایانه دسک تاپ متصل درخواست شده است. آیا می‌خواهید این اجازه را بدهید؟"\n\n"اگر خود شما درخواست بازیابی نداده‌اید، اجازه ادامه این عملیات را ندهید. با این کار همه داده‌هایی که اکنون روی دستگاه است جایگزین می‌شود!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"بازیابی داده‌های من"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"بازیابی نشود"</string>
-    <string name="current_password_text" msgid="8268189555578298067">"لطفاً گذرواژه نسخه پشتیبان فعلی خود را در زیر وارد کنید:"</string>
+    <string name="current_password_text" msgid="8268189555578298067">"لطفاً گذرواژه نسخهٔ پشتیبان فعلی خود را در زیر وارد کنید:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"لطفاً گذرواژه رمزگذاری دستگاه خود را در زیر وارد کنید."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"لطفاً گذرواژه رمزگذاری دستگاه خود را در زیر وارد کنید. این برای رمزگذاری بایگانی پشتیبان نیز مورد استفاده قرار می‌گیرد."</string>
-    <string name="backup_enc_password_text" msgid="4981585714795233099">"لطفاً یک گذرواژه برای رمزگذاری داده‌های کامل نسخه پشتیبانی وارد کنید. اگر این خالی بماند، گذرواژه فعلی نسخه پشتیبان مورد استفاده قرار خواهد گرفت:"</string>
+    <string name="backup_enc_password_text" msgid="4981585714795233099">"لطفاً یک گذرواژه برای رمزگذاری داده‌های کامل نسخهٔ پشتیبانی وارد کنید. اگر این خالی بماند، گذرواژه فعلی نسخهٔ پشتیبان مورد استفاده قرار خواهد گرفت:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"اگر می‌خواهید تمام نسخه پشتیبانی داده را رمزدار کنید، یک گذرواژه در زیر وارد کنید:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"اگر داده بازیابی شده رمزگذاری شده است، لطفاً گذرواژه را در زیر وارد کنید:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"شروع پشتیبان‌گیری..."</string>
diff --git a/packages/DefaultContainerService/res/values-ca/strings.xml b/packages/DefaultContainerService/res/values-ca/strings.xml
index 3af2c55..e19c72c 100644
--- a/packages/DefaultContainerService/res/values-ca/strings.xml
+++ b/packages/DefaultContainerService/res/values-ca/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Assistent d\'accés a paquets"</string>
+    <string name="service_name" msgid="4841491635055379553">"Assist. d\'accés a paquets"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-es-rUS/strings.xml b/packages/DefaultContainerService/res/values-es-rUS/strings.xml
index 670c2c5..19fd655 100644
--- a/packages/DefaultContainerService/res/values-es-rUS/strings.xml
+++ b/packages/DefaultContainerService/res/values-es-rUS/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Asist. p/acceder al paq."</string>
+    <string name="service_name" msgid="4841491635055379553">"Asist. acceso al paquete"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-lt/strings.xml b/packages/DefaultContainerService/res/values-lt/strings.xml
index df5ffef..3faf8cc 100644
--- a/packages/DefaultContainerService/res/values-lt/strings.xml
+++ b/packages/DefaultContainerService/res/values-lt/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Prieig. prie paketo pagalb. priem."</string>
+    <string name="service_name" msgid="4841491635055379553">"Pak. pagalb. prm. prieiga"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-nl/strings.xml b/packages/DefaultContainerService/res/values-nl/strings.xml
index 9ece040..2501099 100644
--- a/packages/DefaultContainerService/res/values-nl/strings.xml
+++ b/packages/DefaultContainerService/res/values-nl/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Helper voor pakkettoegang"</string>
+    <string name="service_name" msgid="4841491635055379553">"Helper pakkettoegang"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-uk/strings.xml b/packages/DefaultContainerService/res/values-uk/strings.xml
index 216d715..1226bd4 100644
--- a/packages/DefaultContainerService/res/values-uk/strings.xml
+++ b/packages/DefaultContainerService/res/values-uk/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
+    <string name="service_name" msgid="4841491635055379553">"Майстер доступу до пакетів"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-vi/strings.xml b/packages/DefaultContainerService/res/values-vi/strings.xml
index 63f1199..885946c 100644
--- a/packages/DefaultContainerService/res/values-vi/strings.xml
+++ b/packages/DefaultContainerService/res/values-vi/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Trình t.giúp truy cập gói"</string>
+    <string name="service_name" msgid="4841491635055379553">"Trình trợ giúp truy cập gói"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
index 65928b1..cb117a2 100644
--- a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
+++ b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"软件包访问帮助程序"</string>
+    <string name="service_name" msgid="4841491635055379553">"应用包访问权限帮助程序"</string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index de078d20..71c8c83 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1658,8 +1658,12 @@
             loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
                     R.string.def_accessibility_screen_reader_url);
 
-            loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
-                    R.bool.def_lockscreen_disabled);
+            if (SystemProperties.getBoolean("ro.lockscreen.disable.default", false) == true) {
+                loadSetting(stmt, Settings.System.LOCKSCREEN_DISABLED, "1");
+            } else {
+                loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
+                        R.bool.def_lockscreen_disabled);
+            }
 
             loadBooleanSetting(stmt, Settings.Secure.DEVICE_PROVISIONED,
                     R.bool.def_device_provisioned);
diff --git a/packages/SystemUI/res/drawable-nodpi/bugdroid.png b/packages/SystemUI/res/drawable-nodpi/bugdroid.png
new file mode 100644
index 0000000..b90675c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/bugdroid.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_alarm.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_100.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_15.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_28.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_43.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_57.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_71.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_85.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim100.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim15.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim28.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim43.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim57.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim71.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim85.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth_connected.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_roam.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_flightmode.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_in.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_out.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_in.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_out.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_alarm.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_100.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_15.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_28.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_43.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_57.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_71.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_85.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim100.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim15.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim28.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim43.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim57.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim71.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim85.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth_connected.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_roam.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_flightmode.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_in.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_out.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_in.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_out.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-tvdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-tvdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_alarm.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_100.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_15.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_28.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_43.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_57.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_71.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_85.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim100.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim15.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim28.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim43.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim57.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim71.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim85.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth_connected.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_roam.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_flightmode.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_in.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_out.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_in.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_out.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/navbar_search_handle.xml b/packages/SystemUI/res/drawable/navbar_search_handle.xml
deleted file mode 100644
index e40fa2c..0000000
--- a/packages/SystemUI/res/drawable/navbar_search_handle.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item
-        android:state_enabled="true"
-        android:state_active="false"
-        android:state_focused="false"
-        android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
-
-    <item
-        android:state_enabled="true"
-        android:state_active="true"
-        android:state_focused="false"
-        android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
-
-</selector>
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
index c8a120d..f56b03b 100644
--- a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -49,7 +49,6 @@
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-                prvandroid:handleDrawable="@drawable/navbar_search_handle"
                 prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
                 prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
                 prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
index 1e4bb57..b871bef 100644
--- a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
@@ -49,7 +49,6 @@
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-                prvandroid:handleDrawable="@drawable/navbar_search_handle"
                 prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
                 prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
                 prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
index 3b6c52e..1fa67bd 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
@@ -35,7 +35,6 @@
         prvandroid:targetDrawables="@array/navbar_search_targets"
         prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
         prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-        prvandroid:handleDrawable="@drawable/navbar_search_handle"
         prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
         prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
         prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
deleted file mode 100644
index 8c2360e..0000000
--- a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.systemui.SearchPanelView
-    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search_panel_container"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent">
-
-    <com.android.internal.widget.multiwaveview.GlowPadView
-        android:id="@+id/glow_pad_view"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/navbar_search_panel_height"
-        android:layout_gravity="left|bottom"
-        android:gravity="top|right"
-        android:layout_marginLeft="-150dip"
-
-        prvandroid:targetDrawables="@array/navbar_search_targets"
-        prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
-        prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-        prvandroid:handleDrawable="@drawable/navbar_search_handle"
-        prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
-        prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
-        prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
-        prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-        prvandroid:feedbackCount="0"
-        prvandroid:vibrationDuration="@integer/config_vibration_duration"
-        prvandroid:alwaysTrackFinger="true"
-        prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
-        prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
-
-</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel.xml b/packages/SystemUI/res/layout/system_bar_notification_panel.xml
index 48a188b..315639e 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel.xml
@@ -57,6 +57,7 @@
             android:id="@+id/notification_scroller"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
+            android:overScrollMode="ifContentScrolls"
             android:layout_weight="1"
             >
             <com.android.systemui.statusbar.policy.NotificationRowLayout
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
index 480d979..2d1bda4 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
@@ -85,7 +85,7 @@
             </FrameLayout>
             <TextView
                 android:id="@+id/mobile_text"
-                style="@style/StatusBarNotificationText"
+                style="@style/SystemBarNotificationText"
                 android:layout_gravity="left|center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -121,7 +121,7 @@
             </FrameLayout>
             <TextView
                 android:id="@+id/wifi_text"
-                style="@style/StatusBarNotificationText"
+                style="@style/SystemBarNotificationText"
                 android:layout_gravity="left|center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -144,7 +144,7 @@
 
             <TextView
                 android:id="@+id/battery_text"
-                style="@style/StatusBarNotificationText"
+                style="@style/SystemBarNotificationText"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="left|center_vertical"
@@ -202,7 +202,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+            android:textAppearance="@style/TextAppearance.SystemBar.Expanded.Clock"
             />
     
         <com.android.systemui.statusbar.policy.DateView
@@ -211,7 +211,7 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="8dp"
             android:layout_marginRight="8dp"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+            android:textAppearance="@style/TextAppearance.SystemBar.Expanded.Date"
             />
 
         <Space
diff --git a/packages/SystemUI/res/layout/system_bar_settings_view.xml b/packages/SystemUI/res/layout/system_bar_settings_view.xml
index e1b2a54..d07e45d 100644
--- a/packages/SystemUI/res/layout/system_bar_settings_view.xml
+++ b/packages/SystemUI/res/layout/system_bar_settings_view.xml
@@ -26,16 +26,16 @@
     <!-- Airplane mode -->
     <LinearLayout
             android:id="@+id/airplane"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/airplane_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_airplane_on"
                 />
         <TextView
                 android:id="@+id/airplane_label"
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_airplane"
                 />
         <Switch
@@ -46,39 +46,39 @@
                 android:layout_marginRight="5dp"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Network -->
     <LinearLayout
             android:id="@+id/network"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/network_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_wifi_on"
                 />
         <TextView
                 android:id="@+id/network_label"
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_wifi_button"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Rotation lock -->
     <LinearLayout
             android:id="@+id/rotate"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/rotate_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_rotate_on"
                 />
         <TextView
                 android:id="@+id/rotate_label"
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_auto_rotation"
                 />
         <Switch
@@ -91,13 +91,13 @@
     </LinearLayout>
     <View
             android:id="@+id/rotate_separator"
-            style="@style/StatusBarPanelSettingsPanelSeparator" />
+            style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Brightness -->
-    <LinearLayout style="@style/StatusBarPanelSettingsRow" >
+    <LinearLayout style="@style/SystemBarPanelSettingsRow" >
         <ImageView
                 android:id="@+id/brightness_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_brightness"
                 />
         <com.android.systemui.statusbar.policy.ToggleSlider
@@ -109,20 +109,20 @@
                 systemui:text="@string/status_bar_settings_auto_brightness_label"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Notifications / Do not disturb -->
     <LinearLayout
             android:id="@+id/do_not_disturb"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/do_not_disturb_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_notification_open"
                 />
         <TextView
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_notifications"
                 />
         <Switch
@@ -133,25 +133,25 @@
                 android:layout_marginRight="5dp"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Link to settings -->
     <LinearLayout
             android:id="@+id/settings"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
 
         <ImageView
                 android:id="@+id/settings"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_quicksettings"
                 />
         <TextView
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_settings_button"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
 </com.android.systemui.statusbar.tablet.SettingsView>
 
diff --git a/packages/SystemUI/res/layout/universe.xml b/packages/SystemUI/res/layout/universe.xml
new file mode 100644
index 0000000..6102d2e
--- /dev/null
+++ b/packages/SystemUI/res/layout/universe.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent" android:layout_height="match_parent">
+    <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true" android:layout_alignParentTop="true"
+        android:src="@drawable/bugdroid" android:scaleType="center" />
+
+    <Button android:id="@+id/close"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:layout_alignParentTop="true" android:layout_alignParentRight="true"
+        android:text="@string/close_universe" />
+
+    <TextView android:id="@+id/title"
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_below="@id/close" android:layout_centerHorizontal="true"
+        android:paddingBottom="16dp"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:gravity="center" />
+
+    <ImageView android:id="@+id/bottom"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:layout_below="@id/title" android:layout_centerHorizontal="true"
+        android:layout_marginTop="16dp" />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index a24a4d7..2db520a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveer sluimerskerm"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programinligting"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Maak toe"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Kennisgewings af"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tik hier om kennisgewings weer aan te skakel."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Die skerm sal outomaties draai."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7c2956c..93547c1 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">" ገፁማያ ማቆያ አንቃ"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"የመተግበሪያ መረጃ"</string>
+    <string name="close_universe" msgid="3736513750241754348">"ዝጋ"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"ማሳወቂያዎች ጠፍተዋል"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"ማስታወቅያዎችን መልሶ ለማብራት እዚህ ጋር መታ አድርግ።"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b2c9ab0..9b975fe 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"تنشيط شاشة التوقف"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"معلومات التطبيق"</string>
+    <string name="close_universe" msgid="3736513750241754348">"إغلاق"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"التنبيهات معطّلة"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"انقر هنا لإعادة تشغيل الإشعارات."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"سيتم تدوير الشاشة تلقائيًا."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c4af8d8..a8a17f0 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Актывацыя экраннай застаўкі"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інфармацыя пра прыкладанне"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Закрыць"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Паведамленні адключаны"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Націсніце тут, каб зноў уключыць апавяшчэнні."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран паварочваецца аўтаматычна."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a4a0e78..0270678 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активиране на скрийнсейвъра"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информация за приложението"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Затваряне"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Известията са изключени"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Докоснете тук, за да включите отново известията."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5a2c9cd..2e48570 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activa el protector de pantalla"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informació de l\'aplicació"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Tanca"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificacions desactivades"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Pica aquí per tornar a activar les notificacions."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2d1f644..c9b6a522 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovat spořič obrazovky"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informace o aplikaci"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zavřít"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Oznámení jsou vypnuta"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Chcete-li oznámení znovu zapnout, klepněte sem."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka se automaticky otočí."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 01068ec..370865c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivér pauseskærm"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Oplysninger om appen"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Luk"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Underretninger slået fra"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tryk her for at slå underretninger til igen."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 011d3a3..65c870f 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Bildschirmschoner aktivieren"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-Details"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Schließen"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Benachrichtigungen aus"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tippen Sie hier, um die Benachrichtigungen wieder zu aktivieren."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0b87777..6e147e2 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ενεργοποίηση προφύλαξης οθόνης"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Πληροφορίες εφαρμογής"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Κλείσιμο"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Ειδοποιήσεις ανενεργές"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Πατήστε εδώ για να ενεργοποιήσετε ξανά τις ειδοποιήσεις."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Θα γίνεται αυτόματη περιστροφή της οθόνης."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f02d09ca..afabd34 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activate screen saver"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App info"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Close"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notifications off"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tap here to turn notifications back on."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index be2bf6e..b83aad5 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar el protector de pantalla"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Cerrar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificaciones desactivadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toca aquí para volver a activar las notificaciones."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index afbceff..c0cab22 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar salvapantallas"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Cerrar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificaciones desactivadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toca aquí para volver a activar las notificaciones."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 318ed04..8adf8ed 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveeri ekraanisäästja"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Rakenduse teave"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Sule"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Teatised väljas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Teatiste uuesti sisselülitamiseks puudutage siin."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekraani pööramine toimub automaatselt."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 104ab038..2c66897 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -22,7 +22,7 @@
     <string name="app_label" msgid="7164937344850004466">"رابط کاربر سیستم"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"پاک کردن"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"مزاحم نشوید"</string>
-    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"نمایش اعلان ها"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"نمایش اعلان‌ها"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"حذف از لیست"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"اطلاعات برنامه"</string>
     <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"برنامه جدیدی موجود نیست"</string>
@@ -33,11 +33,11 @@
   </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"اعلانی موجود نیست"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
-    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان ها"</string>
+    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان‌ها"</string>
     <string name="battery_low_title" msgid="2783104807551211639">"شارژر را متصل کنید"</string>
     <string name="battery_low_subtitle" msgid="1752040062087829196">"باتری در حال کم شدن است."</string>
     <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> باقیمانده است"</string>
-    <string name="invalid_charger" msgid="4549105996740522523">"شارژ USB پشتیبانی نمی شود."\n"فقط از شارژر ارائه شده استفاده کنید."</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"شارژ USB پشتیبانی نمی‌شود."\n"فقط از شارژر ارائه شده استفاده کنید."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"استفاده از باتری"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"تنظیمات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
@@ -45,23 +45,23 @@
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"چرخش خودکار صفحه"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بیصدا"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
-    <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان ها"</string>
+    <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان‌ها"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"تنظیم روش‌های ورودی"</string>
-    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه کلید فیزیکی"</string>
-    <string name="usb_device_permission_prompt" msgid="834698001271562057">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می دهید به دستگاه USB دسترسی داشته باشد؟"</string>
-    <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهد تا به وسیله جانبی USB دسترسی داشته باشد؟"</string>
+    <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه‌کلید فیزیکی"</string>
+    <string name="usb_device_permission_prompt" msgid="834698001271562057">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می‌دهید به دستگاه USB دسترسی داشته باشد؟"</string>
+    <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می‌دهد تا به وسیله جانبی USB دسترسی داشته باشد؟"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"وقتی این دستگاه USB وصل است، <xliff:g id="ACTIVITY">%1$s</xliff:g> باز شود؟"</string>
     <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"وقتی این وسیله جانبی USB وصل است، <xliff:g id="ACTIVITY">%1$s</xliff:g> باز شود؟"</string>
-    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"هیچ برنامه کاربردی نصب شده‌ای با این وسیله جانبی USB کار نمیکند. در <xliff:g id="URL">%1$s</xliff:g> درباره این وسیله جانبی اطلاعات بیشتری کسب کنید"</string>
+    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"هیچ برنامهٔ کاربردی نصب شده‌ای با این وسیله جانبی USB کار نمی‌کند. در <xliff:g id="URL">%1$s</xliff:g> دربارهٔ این وسیله جانبی اطلاعات بیشتری کسب کنید"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"لوازم جانبی USB"</string>
     <string name="label_view" msgid="6304565553218192990">"مشاهده"</string>
-    <string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
-    <string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
+    <string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
+    <string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"بزرگنمایی سازگاری"</string>
-    <string name="compat_mode_help_body" msgid="4946726776359270040">"اگر یک برنامه برای صفحه کوچک تری طراحی شده باشد، یک کنترل بزرگنمایی توسط ساعت نشان داده می شود."</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"اگر یک برنامه برای صفحه کوچک تری طراحی شده باشد، یک کنترل بزرگنمایی توسط ساعت نشان داده می‌شود."</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره تصویر صفحه..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"در حال ذخیره تصویر صفحه..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"تصویر صفحه ذخیره شد."</string>
@@ -69,7 +69,7 @@
     <string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده تصویر صفحه خود، لمس کنید."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"تصویر صفحه گرفته نشد."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"تصویر صفحه ذخیره نشد. ممکن است دستگاه ذخیره‌ در حال استفاده باشد."</string>
-    <string name="usb_preference_title" msgid="6551050377388882787">"گزینه های انتقال فایل USB"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"گزینه‌های انتقال فایل USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"نصب به عنوان دستگاه پخش رسانه (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"تصب به عنوان دوربین (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"برنامه Android File Transfer را برای Mac نصب کنید"</string>
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلان‌ها"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"فعال کردن محافظ صفحهٔ نمایش"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"اطلاعات برنامه"</string>
+    <string name="close_universe" msgid="3736513750241754348">"بستن"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"اعلان‌ها خاموش"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"برای روشن کردن مجدد اعلان‌ها، اینجا را ضربه بزنید."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"صفحه به صورت خودکار می‌چرخد."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a4229b4..bec1b48 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ota näytönsäästäjä käyttöön"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Sovelluksen tiedot"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Sulje"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Ilmoitukset pois käytöstä"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 30b3539..15489f5a 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activer l\'économiseur d\'écran"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informations sur l\'application"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Fermer"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notifications désactivées"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Appuyez ici pour réactiver les notifications."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index aae070a..c66b680 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"स्‍क्रीन सेवर सक्रिय करें"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"एप्‍लिकेशन जानकारी"</string>
+    <string name="close_universe" msgid="3736513750241754348">"बंद करें"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"सूचनाएं बंद"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"सूचनाओं को पुन: चालू करने के लिए यहां टैप करें."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्‍क्रीन स्‍वचालित रूप से घूमेगी."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4a1f35a..1a10ecb 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivirajte čuvar zaslona"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informacije o aplikaciji"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zatvori"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Obavijesti isključene"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon će se automatski zakrenuti."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2ea0f76..25f3e54 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Képernyővédő aktiválása"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Alkalmazásinformáció"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Bezárás"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Értesítések kikapcsolva"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Itt érintse meg az értesítések bekapcsolásához."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A képernyő automatikusan forogni fog."</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a69fc23..3ad4fd1 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan tirai layar"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info aplikasi"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Tutup"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Pemberitahuan mati"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Ketuk di sini untuk menyalakan pemberitahuan lagi."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 432d984..df7f188 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Attiva screensaver"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informazioni applicazione"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Chiudi"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notifiche disattivate"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tocca qui per riattivare le notifiche."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Lo schermo ruoterà automaticamente."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bdc84b6..2e75e72 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"הפעלת שומר מסך"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"פרטי יישום"</string>
+    <string name="close_universe" msgid="3736513750241754348">"סגור"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"מצב התראות כבוי"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"הקש כאן כדי להפעיל מחדש את ההתראות."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 70ba034..2d73518 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"スクリーンセーバーを有効にする"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"アプリ情報"</string>
+    <string name="close_universe" msgid="3736513750241754348">"閉じる"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"通知OFF"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"通知を再度ONにするにはここをタップします。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e54b06c..438734e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"스크린 세이버 활성화"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"앱 정보"</string>
+    <string name="close_universe" msgid="3736513750241754348">"닫기"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"알림 사용 안함"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"알림을 다시 사용하려면 여기를 터치하세요."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 018b5e5..62c6a06 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktyvinti ekrano užsklandą"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programos informacija"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Uždaryti"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Pranešimai išjungti"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Jei norite vėl įjungti pranešimus, palieskite čia."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e708804..5929240 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivizēt ekrānsaudzētāju"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informācija par lietotni"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Aizvērt"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Paziņojumi ir izslēgti"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Pieskarieties šeit, lai atkal ieslēgtu paziņojumus."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 3265cd5..5bf9811 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan gambar skrin"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Maklumat apl"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Tutup"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Pemberitahuan dimatikan"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Ketik di sini untuk menghidupkan kembali pemberitahuan."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a1ee469..9a0b2de 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiver skjermbeskytter"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om app"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Lukk"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Varsler er deaktivert"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Trykk her for å aktivere varsler på nytt."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 936e0958..33bab76 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Schermbeveiliging inschakelen"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-info"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Sluiten"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Meldingen uit"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tik hier om meldingen weer in te schakelen."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Scherm wordt automatisch geroteerd."</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b4a77a2..6a7639f 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Włącz wygaszacz ekranu."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"O aplikacji"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zamknij"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Powiadomienia wyłączone"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Kliknij tutaj, by przywrócić powiadomienia."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d08c529..655c46e 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de ecrã"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações da aplicação"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Fechar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificações desativadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toque aqui para voltar a ativar as notificações."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 596ceec..5fabdfd 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de tela"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações do aplicativo"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Fechar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificações desativadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toque aqui para ativar as notificações novamente."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 16e5719..e0c0886 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -250,6 +250,8 @@
     <skip />
     <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
     <skip />
+    <!-- no translation found for close_universe (3736513750241754348) -->
+    <skip />
     <!-- no translation found for notifications_off_title (8936620513608443224) -->
     <skip />
     <!-- no translation found for notifications_off_text (2529001315769385273) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87eec9f..58a9a9b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ştergeţi toate notificările."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activaţi screensaverul"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informaţii despre aplicaţie"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Închideţi"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificările sunt dezactivate"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Apăsaţi aici pentru a reactiva notificările."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7a7d08f..155238a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активация заставки экрана"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"О приложении"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Закрыть"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Уведомления отключены"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Нажмите здесь, чтобы снова включить уведомления."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8e64487..0c15f6c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovať šetrič obrazovky"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informácie o aplikácii"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zavrieť"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Upozornenia sú vypnuté"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Klepnutím sem upozornenia znova povolíte."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1fa3b21..2b385fc 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Vklop ohranjevalnika zaslona"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Podatki o aplikaciji"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zapri"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Obvestila so izklopljena"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Dotaknite se tukaj, da ponovno vklopite obvestila."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd41e02..c43b66f 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активирање чувара екрана"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информације о апликацији"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Затвори"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Обавештења су искључена"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Додирните овде да бисте поново укључили обавештења."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран ће се аутоматски ротирати."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index afbe0fb..e3a1481 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivera skärmsläckare"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om appen"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Stäng"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Meddelanden inaktiverade"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Knacka lätt här om du vill aktivera meddelanden igen."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8f22b81c..b333bbe 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -51,7 +51,7 @@
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha ziada cha USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Je, ungetaka kufungua  <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string>
     <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Je, ungetaka kufungua  <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string>
-    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Jifunze zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string>
+    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Pata maelezo zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Kifaa cha Usb"</string>
     <string name="label_view" msgid="6304565553218192990">"Ona"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kwa kifaa hiki cha USB tumia chaguo-msingi"</string>
@@ -138,6 +138,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Amilisha hifadhi ya skrini"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Taarifa ya programu"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Funga"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Arifa zimelemazwa"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Gonga hapa ili kuwezesha tena arifa."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrini itazunguka kiotomatiki."</string>
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index 8af700a..de63d9f 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -20,7 +20,7 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources>
-    <integer name="config_maxNotificationIcons">5</integer>
+    <integer name="status_bar_config_maxNotificationIcons">5</integer>
 
     <!-- Whether we're using the tablet-optimized recents interface (we use this
      value at runtime for some things) -->
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 36cbabf..a61fd68 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -17,16 +17,16 @@
 -->
 <resources>
     <!-- size at which Notification icons will be drawn in the status bar -->
-    <dimen name="status_bar_icon_drawing_size">24dip</dimen>
+    <dimen name="system_bar_icon_drawing_size">24dip</dimen>
 
     <!-- opacity at which Notification icons will be drawn in the status bar -->
-    <item type="dimen" name="status_bar_icon_drawing_alpha">100%</item>
+    <item type="dimen" name="system_bar_icon_drawing_alpha">100%</item>
 
     <!-- The width of the view containing non-menu status bar icons -->
-    <dimen name="navigation_key_width">80dip</dimen>
+    <dimen name="system_bar_navigation_key_width">80dip</dimen>
 
     <!-- The width of the view containing the menu status bar icon -->
-    <dimen name="navigation_menu_key_width">80dip</dimen>
+    <dimen name="system_bar_navigation_menu_key_width">80dip</dimen>
 
     <!-- ======================================== -->
     <!-- The following resources were recently moved from sw600dp; there may
diff --git a/packages/SystemUI/res/values-sw720dp/styles.xml b/packages/SystemUI/res/values-sw720dp/styles.xml
index 684258a..e0b1774 100644
--- a/packages/SystemUI/res/values-sw720dp/styles.xml
+++ b/packages/SystemUI/res/values-sw720dp/styles.xml
@@ -16,12 +16,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="StatusBarNotificationText">
+    <style name="SystemBarNotificationText">
         <item name="android:textSize">16sp</item>
         <item name="android:textColor">#ff999999</item>
     </style>
 
-    <style name="StatusBarPanelSettingsRow">
+    <style name="SystemBarPanelSettingsRow">
         <item name="android:paddingRight">16dp</item>
         <item name="android:layout_height">64dp</item>
         <item name="android:layout_width">match_parent</item>
@@ -29,13 +29,13 @@
         <item name="android:background">?android:attr/listChoiceBackgroundIndicator</item>
     </style>
 
-    <style name="StatusBarPanelSettingsIcon">
+    <style name="SystemBarPanelSettingsIcon">
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_width">64dp</item>
         <item name="android:scaleType">center</item>
     </style>
 
-    <style name="StatusBarPanelSettingsContents">
+    <style name="SystemBarPanelSettingsContents">
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_width">0dp</item>
         <item name="android:layout_weight">1</item>
@@ -44,27 +44,27 @@
         <item name="android:textSize">18sp</item>
     </style>
 
-    <style name="StatusBarPanelSettingsPanelSeparator">
+    <style name="SystemBarPanelSettingsPanelSeparator">
         <item name="android:layout_marginRight">0dp</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">1dp</item>
         <item name="android:background">@android:drawable/divider_horizontal_dark</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
+    <style name="TextAppearance.SystemBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
         <item name="android:textSize">30dp</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Expanded.Clock">
+    <style name="TextAppearance.SystemBar.Expanded.Clock" parent="@style/TextAppearance.StatusBar.Expanded.Clock">
         <item name="android:textSize">48dp</item>
         <item name="android:fontFamily">sans-serif-light</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">#ffffff</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Expanded.Date">
+    <style name="TextAppearance.SystemBar.Expanded.Date" parent="@style/TextAppearance.StatusBar.Expanded.Date">
         <item name="android:textSize">14dp</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">#666666</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 70f0b9b..4d46a5d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"เปิดโปรแกรมรักษาหน้าจอ"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ข้อมูลแอป"</string>
+    <string name="close_universe" msgid="3736513750241754348">"ปิด"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"การแจ้งเตือนปิดอยู่"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"หน้าจอจะหมุนโดยอัตโนมัติ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1c4185..a93e511 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"I-activate ang screen saver"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Impormasyon ng app"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Isara"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Naka-off ang mga notification"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tumapik dito upang muling i-on ang mga notification."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Awtomatikong iikot ang screen."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9bf8f76..0f6af69 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ekran koruyucuyu etkinleştir"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Uygulama bilgileri"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Kapat"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Bildirimler kapalı"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 165baae..5922e24 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активувати заставку"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інформація про програму"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Закрити"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Сповіщення вимкнено"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Торкніться тут, щоб знову ввімкнути сповіщення."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index eef2c83..15141c9 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Kích hoạt trình bảo vệ màn hình"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Thông tin về ứng dụng"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Đóng"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Tắt thông báo"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Chạm vào đây để bật lại thông báo."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ca29738..19470e6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"激活屏幕保护程序"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"应用信息"</string>
+    <string name="close_universe" msgid="3736513750241754348">"关闭"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"通知功能已停用"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"点按此处可重新启用通知功能。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8fa4af9..fa2e9d1 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -142,6 +142,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"啟用螢幕保護程式"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"應用程式資訊"</string>
+    <string name="close_universe" msgid="3736513750241754348">"關閉"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"關閉通知"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"輕按這裡即可重新開啟通知。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4f3e787..1e11f04 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -140,6 +140,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
     <string name="dreams_dock_launcher" msgid="3541196417659166245">"Yenza ukuthi iskrini seyiva sisebenze"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Ulwazi lohlelo lokusebenza"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Vala"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Izaziso zivaliwe"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Thepha lapha ukuvula futhi izaziso."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Isikrini sizophenduka ngokuzenzakalela."</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 26dba67..66add1a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -65,5 +65,8 @@
 
     <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
     <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
+
+    <!-- The length of the vibration when the notificaiotn pops open. -->
+    <integer name="one_finger_pop_duration_ms">10</integer>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6c40461..eed8e77 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -150,4 +150,7 @@
 
     <!-- Height of the carrier/wifi name label -->
     <dimen name="carrier_label_height">24dp</dimen>
+
+    <!-- The distance you can pull a notificaiton before it pops open -->
+    <dimen name="one_finger_pop_limit">96dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f18e33e..2ce950f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -370,6 +370,9 @@
          application -->
     <string name="status_bar_notification_inspect_item_title">App info</string>
 
+    <!-- [CHAR LIMIT=NONE] -->
+    <string name="close_universe">Close</string>
+
     <!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
          mode) -->
     <string name="notifications_off_title">Notifications off</string>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 5dd15c3..10dcd9e 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -22,24 +22,31 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.os.Vibrator;
 import android.util.Slog;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 
+import java.util.Stack;
+
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
     public interface Callback {
         View getChildAtRawPosition(float x, float y);
         View getChildAtPosition(float x, float y);
+        View getPreviousChild(View currentChild);
         boolean canChildBeExpanded(View v);
         boolean setUserExpandedChild(View v, boolean userxpanded);
     }
 
     private static final String TAG = "ExpandHelper";
     protected static final boolean DEBUG = false;
+    protected static final boolean DEBUG_SCALE = false;
+    protected static final boolean DEBUG_GLOW = false;
     private static final long EXPAND_DURATION = 250;
     private static final long GLOW_DURATION = 150;
 
@@ -63,6 +70,9 @@
     private Context mContext;
 
     private boolean mStretching;
+    private boolean mPullingWithOneFinger;
+    private boolean mWatchingForPull;
+    private boolean mHasPopped;
     private View mEventSource;
     private View mCurrView;
     private View mCurrViewTopGlow;
@@ -70,7 +80,12 @@
     private float mOldHeight;
     private float mNaturalHeight;
     private float mInitialTouchFocusY;
+    private float mInitialTouchY;
     private float mInitialTouchSpan;
+    private int mTouchSlop;
+    private int mLastMotionY;
+    private float mPopLimit;
+    private int mPopDuration;
     private Callback mCallback;
     private ScaleGestureDetector mDetector;
     private ViewScaler mScaler;
@@ -78,6 +93,7 @@
     private AnimatorSet mGlowAnimationSet;
     private ObjectAnimator mGlowTopAnimation;
     private ObjectAnimator mGlowBottomAnimation;
+    private Vibrator mVibrator;
 
     private int mSmallSize;
     private int mLargeSize;
@@ -85,6 +101,8 @@
 
     private int mGravity;
 
+    private View mScrollView;
+
     private class ViewScaler {
         View mView;
 
@@ -93,7 +111,7 @@
             mView = v;
         }
         public void setHeight(float h) {
-            if (DEBUG) Slog.v(TAG, "SetHeight: setting to " + h);
+            if (DEBUG_SCALE) Slog.v(TAG, "SetHeight: setting to " + h);
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
             lp.height = (int)h;
             mView.setLayoutParams(lp);
@@ -108,7 +126,8 @@
         }
         public int getNaturalHeight(int maximum) {
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
-            if (DEBUG) Slog.v(TAG, "Inspecting a child of type: " + mView.getClass().getName());
+            if (DEBUG_SCALE) Slog.v(TAG, "Inspecting a child of type: " +
+                    mView.getClass().getName());
             int oldHeight = lp.height;
             lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
             mView.setLayoutParams(lp);
@@ -123,6 +142,17 @@
         }
     }
 
+    class PopState {
+        View mCurrView;
+        View mCurrViewTopGlow;
+        View mCurrViewBottomGlow;
+        float mOldHeight;
+        float mNaturalHeight;
+        float mInitialTouchY;
+    }
+
+    private Stack<PopState> popStack;
+
     /**
      * Handle expansion gestures to expand and contract children of the callback.
      *
@@ -138,10 +168,13 @@
         mLargeSize = large;
         mContext = context;
         mCallback = callback;
+        popStack = new Stack<PopState>();
         mScaler = new ViewScaler();
         mGravity = Gravity.TOP;
         mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
         mScaleAnimation.setDuration(EXPAND_DURATION);
+        mPopLimit = mContext.getResources().getDimension(R.dimen.one_finger_pop_limit);
+        mPopDuration = mContext.getResources().getInteger(R.integer.one_finger_pop_duration_ms);
 
         AnimatorListenerAdapter glowVisibilityController = new AnimatorListenerAdapter() {
             @Override
@@ -169,38 +202,30 @@
         mGlowAnimationSet.play(mGlowTopAnimation).with(mGlowBottomAnimation);
         mGlowAnimationSet.setDuration(GLOW_DURATION);
 
+        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
+        mTouchSlop = configuration.getScaledTouchSlop();
+
         mDetector =
                 new ScaleGestureDetector(context,
                                          new ScaleGestureDetector.SimpleOnScaleGestureListener() {
             @Override
             public boolean onScaleBegin(ScaleGestureDetector detector) {
-                if (DEBUG) Slog.v(TAG, "onscalebegin()");
+                if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
                 float x = detector.getFocusX();
                 float y = detector.getFocusY();
 
-                View v = null;
-                if (mEventSource != null) {
-                    int[] location = new int[2];
-                    mEventSource.getLocationOnScreen(location);
-                    x += (float) location[0];
-                    y += (float) location[1];
-                    v = mCallback.getChildAtRawPosition(x, y);
-                } else {
-                    v = mCallback.getChildAtPosition(x, y);
-                }
-
                 // your fingers have to be somewhat close to the bounds of the view in question
                 mInitialTouchFocusY = detector.getFocusY();
                 mInitialTouchSpan = Math.abs(detector.getCurrentSpan());
-                if (DEBUG) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
+                if (DEBUG_SCALE) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
 
-                mStretching = initScale(v);
+                mStretching = initScale(findView(x, y));
                 return mStretching;
             }
 
             @Override
             public boolean onScale(ScaleGestureDetector detector) {
-                if (DEBUG) Slog.v(TAG, "onscale() on " + mCurrView);
+                if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
 
                 // are we scaling or dragging?
                 float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan;
@@ -210,33 +235,71 @@
                 drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
                 float pull = Math.abs(drag) + Math.abs(span) + 1f;
                 float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
-                if (DEBUG) Slog.d(TAG, "current span handle is: " + hand);
-                hand = hand + mOldHeight;
-                float target = hand;
-                if (DEBUG) Slog.d(TAG, "target is: " + target);
-                hand = hand < mSmallSize ? mSmallSize : (hand > mLargeSize ? mLargeSize : hand);
-                hand = hand > mNaturalHeight ? mNaturalHeight : hand;
-                if (DEBUG) Slog.d(TAG, "scale continues: hand =" + hand);
-                mScaler.setHeight(hand);
+                float target = hand + mOldHeight;
+                float newHeight = clamp(target);
+                mScaler.setHeight(newHeight);
 
-                // glow if overscale
-                float stretch = (float) Math.abs((target - hand) / mMaximumStretch);
-                float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
-                if (DEBUG) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
-                setGlow(GLOW_BASE + strength * (1f - GLOW_BASE));
+                setGlow(calculateGlow(target, newHeight));
                 return true;
             }
 
             @Override
             public void onScaleEnd(ScaleGestureDetector detector) {
-                if (DEBUG) Slog.v(TAG, "onscaleend()");
+                if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
                 // I guess we're alone now
-                if (DEBUG) Slog.d(TAG, "scale end");
+                if (DEBUG_SCALE) Slog.d(TAG, "scale end");
                 finishScale(false);
+                clearView();
+                mStretching = false;
             }
         });
     }
 
+    private float clamp(float target) {
+        float out = target;
+        out = out < mSmallSize ? mSmallSize : (out > mLargeSize ? mLargeSize : out);
+        out = out > mNaturalHeight ? mNaturalHeight : out;
+        return out;
+    }
+
+    private View findView(float x, float y) {
+        View v = null;
+        if (mEventSource != null) {
+            int[] location = new int[2];
+            mEventSource.getLocationOnScreen(location);
+            x += (float) location[0];
+            y += (float) location[1];
+            v = mCallback.getChildAtRawPosition(x, y);
+        } else {
+            v = mCallback.getChildAtPosition(x, y);
+        }
+        return v;
+    }
+
+    private boolean isInside(View v, float x, float y) {
+        if (DEBUG) Slog.d(TAG, "isinside (" + x + ", " + y + ")");
+
+        if (v == null) {
+            if (DEBUG) Slog.d(TAG, "isinside null subject");
+            return false;
+        }
+        if (mEventSource != null) {
+            int[] location = new int[2];
+            mEventSource.getLocationOnScreen(location);
+            x += (float) location[0];
+            y += (float) location[1];
+            if (DEBUG) Slog.d(TAG, "  to global (" + x + ", " + y + ")");
+        }
+        int[] location = new int[2];
+        v.getLocationOnScreen(location);
+        x -= (float) location[0];
+        y -= (float) location[1];
+        if (DEBUG) Slog.d(TAG, "  to local (" + x + ", " + y + ")");
+        if (DEBUG) Slog.d(TAG, "  inside (" + v.getWidth() + ", " + v.getHeight() + ")");
+        boolean inside = (x > 0f && y > 0f && x < v.getWidth() & y < v.getHeight());
+        return inside;
+    }
+
     public void setEventSource(View eventSource) {
         mEventSource = eventSource;
     }
@@ -245,13 +308,26 @@
         mGravity = gravity;
     }
 
+    public void setScrollView(View scrollView) {
+        mScrollView = scrollView;
+    }
+
+    private float calculateGlow(float target, float actual) {
+        // glow if overscale
+        if (DEBUG_GLOW) Slog.d(TAG, "target: " + target + " actual: " + actual);
+        float stretch = (float) Math.abs((target - actual) / mMaximumStretch);
+        float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
+        if (DEBUG_GLOW) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
+        return (GLOW_BASE + strength * (1f - GLOW_BASE));
+    }
+
     public void setGlow(float glow) {
         if (!mGlowAnimationSet.isRunning() || glow == 0f) {
             if (mGlowAnimationSet.isRunning()) {
-                mGlowAnimationSet.cancel();
+                mGlowAnimationSet.end();
             }
             if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null) {
-                if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) { 
+                if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) {
                     // animate glow in and out
                     mGlowTopAnimation.setTarget(mCurrViewTopGlow);
                     mGlowBottomAnimation.setTarget(mCurrViewBottomGlow);
@@ -278,23 +354,120 @@
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (DEBUG) Slog.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
-                         " stretching=" + mStretching);
+                         " stretching=" + mStretching +
+                         " onefinger=" + mPullingWithOneFinger);
+        // check for a two-finger gesture
         mDetector.onTouchEvent(ev);
-        return mStretching;
+        if (mStretching) {
+            return true;
+        } else {
+            final int action = ev.getAction();
+            if ((action == MotionEvent.ACTION_MOVE) && mPullingWithOneFinger) {
+                return true;
+            }
+            if (mScrollView != null && mScrollView.getScrollY() > 0) {
+                return false;
+            }
+            switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_MOVE: {
+                if (mWatchingForPull) {
+                    final int x = (int) ev.getX();
+                    final int y = (int) ev.getY();
+                    final int yDiff = y - mLastMotionY;
+                    if (yDiff > mTouchSlop) {
+                        mLastMotionY = y;
+                        mPullingWithOneFinger = initScale(findView(x, y));
+                        if (mPullingWithOneFinger) {
+                            mInitialTouchY = mLastMotionY;
+                            mHasPopped = false;
+                        }
+                    }
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_DOWN:
+                mWatchingForPull = isInside(mScrollView, ev.getX(), ev.getY());
+                mLastMotionY = (int) ev.getY();
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                if (mPullingWithOneFinger) {
+                    finishScale(false);
+                    clearView();
+                }
+                mPullingWithOneFinger = false;
+                mWatchingForPull = false;
+                break;
+            }
+            return mPullingWithOneFinger;
+        }
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
-        if (DEBUG) Slog.d(TAG, "touch: act=" + (action) + " stretching=" + mStretching);
+        if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + (action) +
+                         " stretching=" + mStretching +
+                         " onefinger=" + mPullingWithOneFinger);
         if (mStretching) {
-            if (DEBUG) Slog.d(TAG, "detector ontouch");
             mDetector.onTouchEvent(ev);
         }
         switch (action) {
+            case MotionEvent.ACTION_MOVE: {
+                if (mPullingWithOneFinger) {
+                    float target = ev.getY() - mInitialTouchY + mOldHeight;
+                    float newHeight = clamp(target);
+                    if (mHasPopped || target > mPopLimit) {
+                        if (!mHasPopped) {
+                            vibrate(mPopDuration);
+                            mHasPopped = true;
+                        }
+                        mScaler.setHeight(newHeight);
+                        // glow if overscale
+                        if (target > mNaturalHeight) {
+                            View previous = mCallback.getPreviousChild(mCurrView);
+                            if (previous != null) {
+                                setGlow(0f);
+                                pushView(previous);
+                                initScale(previous);
+                                mInitialTouchY = ev.getY();
+                                target = mOldHeight;
+                                newHeight = clamp(target);
+                                mHasPopped = false;
+                            } else {
+                                setGlow(calculateGlow(target, newHeight));
+                            }
+                        } else if (target < mSmallSize && !popStack.empty()) {
+                            setGlow(0f);
+                            initScale(popView());
+                            mInitialTouchY = ev.getY();
+                            setGlow(GLOW_BASE);
+                        } else {
+                            setGlow(calculateGlow(target, newHeight));
+                        }
+                    } else {
+                         if (target < mSmallSize && !popStack.empty()) {
+                            setGlow(0f);
+                            initScale(popView());
+                            mInitialTouchY = ev.getY();
+                            setGlow(GLOW_BASE);
+                         } else {
+                             setGlow(calculateGlow(4f * target, mSmallSize));
+                         }
+                    }
+                    return true;
+                }
+                break;
+            }
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
                 if (DEBUG) Slog.d(TAG, "cancel");
                 mStretching = false;
+                if (mPullingWithOneFinger) {
+                    finishScale(false);
+                    mPullingWithOneFinger = false;
+                }
                 clearView();
                 break;
         }
@@ -303,7 +476,6 @@
     private boolean initScale(View v) {
         if (v != null) {
             if (DEBUG) Slog.d(TAG, "scale begins on view: " + v);
-            mStretching = true;
             setView(v);
             setGlow(GLOW_BASE);
             mScaler.setView(v);
@@ -318,8 +490,10 @@
             if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
                         " mNaturalHeight: " + mNaturalHeight);
             v.getParent().requestDisallowInterceptTouchEvent(true);
+            return true;
+        } else {
+            return false;
         }
-        return mStretching;
     }
 
     private void finishScale(boolean force) {
@@ -330,21 +504,21 @@
         } else {
             h = (force || h < mNaturalHeight) ? mSmallSize : mNaturalHeight;
         }
-        if (DEBUG && mCurrView != null) mCurrView.setBackgroundColor(0);
         if (mScaleAnimation.isRunning()) {
             mScaleAnimation.cancel();
         }
         mScaleAnimation.setFloatValues(h);
         mScaleAnimation.setupStartValues();
         mScaleAnimation.start();
-        mStretching = false;
         setGlow(0f);
         mCallback.setUserExpandedChild(mCurrView, h == mNaturalHeight);
         if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
-        clearView();
     }
 
     private void clearView() {
+        while (!popStack.empty()) {
+            popStack.pop();
+        }
         mCurrView = null;
         mCurrViewTopGlow = null;
         mCurrViewBottomGlow = null;
@@ -357,7 +531,7 @@
             mCurrViewTopGlow = g.findViewById(R.id.top_glow);
             mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
             if (DEBUG) {
-                String debugLog = "Looking for glows: " + 
+                String debugLog = "Looking for glows: " +
                         (mCurrViewTopGlow != null ? "found top " : "didn't find top") +
                         (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
                 Slog.v(TAG,  debugLog);
@@ -365,10 +539,49 @@
         }
     }
 
+    private void pushView(View v) {
+        PopState state = new PopState();
+        state.mCurrView = mCurrView;
+        state.mCurrViewTopGlow = mCurrViewTopGlow;
+        state.mCurrViewBottomGlow = mCurrViewBottomGlow;
+        state.mOldHeight = mOldHeight;
+        state.mNaturalHeight = mNaturalHeight;
+        state.mInitialTouchY = mInitialTouchY;
+        popStack.push(state);
+    }
+
+    private View popView() {
+        if (popStack.empty()) {
+            return null;
+        }
+
+        PopState state = popStack.pop();
+        mCurrView = state.mCurrView;
+        mCurrViewTopGlow = state.mCurrViewTopGlow;
+        mCurrViewBottomGlow = state.mCurrViewBottomGlow;
+        mOldHeight = state.mOldHeight;
+        mNaturalHeight = state.mNaturalHeight;
+        mInitialTouchY = state.mInitialTouchY;
+
+        return mCurrView;
+    }
+
     @Override
     public void onClick(View v) {
         initScale(v);
         finishScale(true);
+        clearView();
+    }
 
+    /**
+     * Triggers haptic feedback.
+     */
+    private synchronized void vibrate(long duration) {
+        if (mVibrator == null) {
+            mVibrator = (android.os.Vibrator)
+                    mContext.getSystemService(Context.VIBRATOR_SERVICE);
+        }
+        mVibrator.vibrate(duration);
     }
 }
+
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index b0a7c4b..a72074e 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -294,13 +294,6 @@
                 updateWallpaperLocked();
             }
 
-            if (mBackground == null) {
-                // If we somehow got to this point after we have last flushed
-                // the wallpaper, well we really need it to draw again.  So
-                // seems like we need to reload it.  Ouch.
-                updateWallpaperLocked();
-            }
-
             SurfaceHolder sh = getSurfaceHolder();
             final Rect frame = sh.getSurfaceFrame();
             final int dw = frame.width();
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
new file mode 100644
index 0000000..4852a3e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.IWindowSession;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewRootImpl;
+import android.view.WindowManager;
+import android.view.animation.Transformation;
+import android.widget.FrameLayout;
+
+public class UniverseBackground extends FrameLayout {
+    static final String TAG = "UniverseBackground";
+    static final boolean SPEW = false;
+    static final boolean CHATTY = false;
+
+    final IWindowSession mSession;
+    final View mContent;
+    final View mBottomAnchor;
+
+    final Runnable mAnimationCallback = new Runnable() {
+        @Override
+        public void run() {
+            doAnimation(mChoreographer.getFrameTimeNanos());
+        }
+    };
+
+    // fling gesture tuning parameters, scaled to display density
+    private float mSelfExpandVelocityPx; // classic value: 2000px/s
+    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
+    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
+    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
+    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
+    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
+    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
+
+    private float mExpandAccelPx; // classic value: 2000px/s/s
+    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
+
+    static final int STATE_CLOSED = 0;
+    static final int STATE_OPENING = 1;
+    static final int STATE_OPEN = 2;
+    private int mState = STATE_CLOSED;
+
+    private float mDragStartX, mDragStartY;
+    private float mAverageX, mAverageY;
+
+    // position
+    private int[] mPositionTmp = new int[2];
+    private boolean mExpanded;
+    private boolean mExpandedVisible;
+
+    private boolean mTracking;
+    private VelocityTracker mVelocityTracker;
+
+    private Choreographer mChoreographer;
+    private boolean mAnimating;
+    private boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
+    private float mAnimY;
+    private float mAnimVel;
+    private float mAnimAccel;
+    private long mAnimLastTimeNanos;
+    private boolean mAnimatingReveal = false;
+
+    private int mYDelta = 0;
+    private Transformation mUniverseTransform = new Transformation();
+    private final float[] mTmpFloats = new float[9];
+
+    public UniverseBackground(Context context) {
+        super(context);
+        setBackgroundColor(0xff000000);
+        mSession = ViewRootImpl.getWindowSession(context.getMainLooper());
+        mContent = View.inflate(context, R.layout.universe, null);
+        addView(mContent);
+        mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
+            @Override public void onClick(View v) {
+                animateCollapse();
+            }
+        });
+        mBottomAnchor = mContent.findViewById(R.id.bottom);
+        mChoreographer = Choreographer.getInstance();
+        loadDimens();
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        loadDimens();
+    }
+
+    private void loadDimens() {
+        final Resources res = getContext().getResources();
+        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
+        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
+        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
+        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
+
+        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
+        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
+
+        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
+        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
+
+        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
+    }
+
+    private void computeAveragePos(MotionEvent event) {
+        final int num = event.getPointerCount();
+        float x = 0, y = 0;
+        for (int i=0; i<num; i++) {
+            x += event.getX(i);
+            y += event.getY(i);
+        }
+        mAverageX = x / num;
+        mAverageY = y / num;
+    }
+
+    private void sendUniverseTransform() {
+        if (getWindowToken() != null) {
+            mUniverseTransform.getMatrix().getValues(mTmpFloats);
+            try {
+                mSession.setUniverseTransform(getWindowToken(), mUniverseTransform.getAlpha(),
+                        mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y],
+                        mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
+                        mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    public WindowManager.LayoutParams getLayoutParams(Display display) {
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND,
+                    0
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                PixelFormat.OPAQUE);
+        // this will allow the window to run in an overlay on devices that support this
+        if (ActivityManager.isHighEndGfx(display)) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        }
+        lp.setTitle("UniverseBackground");
+        lp.windowAnimations = 0;
+        return lp;
+    }
+
+    private int getExpandedViewMaxHeight() {
+        return mBottomAnchor.getTop();
+    }
+
+    public void animateCollapse() {
+        animateCollapse(1.0f);
+    }
+
+    public void animateCollapse(float velocityMultiplier) {
+        if (SPEW) {
+            Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+                    + " mExpandedVisible=" + mExpandedVisible
+                    + " mExpanded=" + mExpanded
+                    + " mAnimating=" + mAnimating
+                    + " mAnimY=" + mAnimY
+                    + " mAnimVel=" + mAnimVel);
+        }
+
+        mState = STATE_CLOSED;
+        if (!mExpandedVisible) {
+            return;
+        }
+
+        int y;
+        if (mAnimating) {
+            y = (int)mAnimY;
+        } else {
+            y = getExpandedViewMaxHeight()-1;
+        }
+        // Let the fling think that we're open so it goes in the right direction
+        // and doesn't try to re-open the windowshade.
+        mExpanded = true;
+        prepareTracking(y, false);
+        performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
+    }
+
+    private void updateUniverseScale() {
+        if (mYDelta > 0) {
+            int w = getWidth();
+            int h = getHeight();
+            float scale = (h-mYDelta+.5f) / (float)h;
+            mUniverseTransform.getMatrix().setScale(scale, scale, w/2, h);
+            if (CHATTY) Log.i(TAG, "w=" + w + " h=" + h + " scale=" + scale
+                    + ": " + mUniverseTransform);
+            sendUniverseTransform();
+            if (getVisibility() != VISIBLE) {
+                setVisibility(VISIBLE);
+            }
+        } else {
+            if (CHATTY) Log.i(TAG, "mYDelta=" + mYDelta);
+            mUniverseTransform.clear();
+            sendUniverseTransform();
+            if (getVisibility() == VISIBLE) {
+                setVisibility(GONE);
+            }
+        }
+    }
+
+    void resetLastAnimTime() {
+        mAnimLastTimeNanos = System.nanoTime();
+        if (SPEW) {
+            Throwable t = new Throwable();
+            t.fillInStackTrace();
+            Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
+        }
+    }
+
+    void doAnimation(long frameTimeNanos) {
+        if (mAnimating) {
+            if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
+            if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
+            incrementAnim(frameTimeNanos);
+            if (SPEW) {
+                Slog.d(TAG, "doAnimation after  mAnimY=" + mAnimY);
+            }
+
+            if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
+                if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
+                mAnimating = false;
+                mYDelta = getExpandedViewMaxHeight();
+                updateUniverseScale();
+                mExpanded = true;
+                mState = STATE_OPEN;
+                return;
+            }
+
+            if (mAnimY <= 0 && mClosing) {
+                if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
+                mAnimating = false;
+                mYDelta = 0;
+                updateUniverseScale();
+                mExpanded = false;
+                mState = STATE_CLOSED;
+                return;
+            }
+
+            mYDelta = (int)mAnimY;
+            updateUniverseScale();
+            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
+                    mAnimationCallback, null);
+        }
+    }
+
+    void stopTracking() {
+        mTracking = false;
+        mVelocityTracker.recycle();
+        mVelocityTracker = null;
+    }
+
+    void incrementAnim(long frameTimeNanos) {
+        final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
+        final float t = deltaNanos * 0.000000001f;                  // ns -> s
+        final float y = mAnimY;
+        final float v = mAnimVel;                                   // px/s
+        final float a = mAnimAccel;                                 // px/s/s
+        mAnimY = y + (v*t) + (0.5f*a*t*t);                          // px
+        mAnimVel = v + (a*t);                                       // px/s
+        mAnimLastTimeNanos = frameTimeNanos;                        // ns
+        //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
+        //        + " mAnimAccel=" + mAnimAccel);
+    }
+
+    void prepareTracking(int y, boolean opening) {
+        if (CHATTY) {
+            Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
+        }
+
+        mTracking = true;
+        mVelocityTracker = VelocityTracker.obtain();
+        if (opening) {
+            mAnimAccel = mExpandAccelPx;
+            mAnimVel = mFlingExpandMinVelocityPx;
+            mAnimY = y;
+            mAnimating = true;
+            mAnimatingReveal = true;
+            resetLastAnimTime();
+            mExpandedVisible = true;
+        }
+        if (mAnimating) {
+            mAnimating = false;
+            mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
+                    mAnimationCallback, null);
+        }
+    }
+
+    void performFling(int y, float vel, boolean always) {
+        if (CHATTY) {
+            Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel);
+        }
+
+        mAnimatingReveal = false;
+
+        mAnimY = y;
+        mAnimVel = vel;
+
+        //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
+
+        if (mExpanded) {
+            if (!always && (
+                    vel > mFlingCollapseMinVelocityPx
+                    || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
+                        vel > -mFlingExpandMinVelocityPx))) {
+                // We are expanded, but they didn't move sufficiently to cause
+                // us to retract.  Animate back to the expanded position.
+                mAnimAccel = mExpandAccelPx;
+                if (vel < 0) {
+                    mAnimVel = 0;
+                }
+            }
+            else {
+                // We are expanded and are now going to animate away.
+                mAnimAccel = -mCollapseAccelPx;
+                if (vel > 0) {
+                    mAnimVel = 0;
+                }
+            }
+        } else {
+            if (always || (
+                    vel > mFlingExpandMinVelocityPx
+                    || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
+                        vel > -mFlingCollapseMinVelocityPx))) {
+                // We are collapsed, and they moved enough to allow us to
+                // expand.  Animate in the notifications.
+                mAnimAccel = mExpandAccelPx;
+                if (vel < 0) {
+                    mAnimVel = 0;
+                }
+            }
+            else {
+                // We are collapsed, but they didn't move sufficiently to cause
+                // us to retract.  Animate back to the collapsed position.
+                mAnimAccel = -mCollapseAccelPx;
+                if (vel > 0) {
+                    mAnimVel = 0;
+                }
+            }
+        }
+        //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
+        //        + " mAnimAccel=" + mAnimAccel);
+
+        resetLastAnimTime();
+        mAnimating = true;
+        mClosing = mAnimAccel < 0;
+        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
+                mAnimationCallback, null);
+        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
+                mAnimationCallback, null);
+
+        stopTracking();
+    }
+
+    private void trackMovement(MotionEvent event) {
+        mVelocityTracker.addMovement(event);
+    }
+
+    public boolean consumeEvent(MotionEvent event) {
+        if (mState == STATE_CLOSED) {
+            if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
+                // Second finger down, time to start opening!
+                computeAveragePos(event);
+                mDragStartX = mAverageX;
+                mDragStartY = mAverageY;
+                mYDelta = 0;
+                mUniverseTransform.clear();
+                sendUniverseTransform();
+                setVisibility(VISIBLE);
+                mState = STATE_OPENING;
+                prepareTracking((int)mDragStartY, true);
+                mVelocityTracker.clear();
+                trackMovement(event);
+                return true;
+            }
+            return false;
+        }
+
+        if (mState == STATE_OPENING) {
+            if (event.getActionMasked() == MotionEvent.ACTION_UP
+                    || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+                mVelocityTracker.computeCurrentVelocity(1000);
+                computeAveragePos(event);
+
+                float yVel = mVelocityTracker.getYVelocity();
+                boolean negative = yVel < 0;
+
+                float xVel = mVelocityTracker.getXVelocity();
+                if (xVel < 0) {
+                    xVel = -xVel;
+                }
+                if (xVel > mFlingGestureMaxXVelocityPx) {
+                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
+                }
+
+                float vel = (float)Math.hypot(yVel, xVel);
+                if (negative) {
+                    vel = -vel;
+                }
+
+                if (CHATTY) {
+                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
+                        mVelocityTracker.getXVelocity(),
+                        mVelocityTracker.getYVelocity(),
+                        xVel, yVel,
+                        vel));
+                }
+
+                performFling((int)mAverageY, vel, false);
+                mState = STATE_OPEN;
+                return true;
+            }
+
+            computeAveragePos(event);
+            mYDelta = (int)(mAverageY - mDragStartY);
+            if (mYDelta > getExpandedViewMaxHeight()) {
+                mYDelta = getExpandedViewMaxHeight();
+            }
+            updateUniverseScale();
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index 296b640..18ad682 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -25,7 +25,6 @@
 import android.graphics.drawable.Drawable;
 import android.util.Slog;
 import android.view.View;
-import android.view.ViewRootImpl;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index f5894ea..fefd0e8 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -53,7 +53,6 @@
 
     private AsyncTask<Void, ArrayList<TaskDescription>, Void> mTaskLoader;
     private AsyncTask<Void, TaskDescription, Void> mThumbnailLoader;
-    private final Handler mHandler;
 
     private int mIconDpi;
     private Bitmap mDefaultThumbnailBackground;
@@ -96,8 +95,6 @@
         // updated thumbnails
         final ActivityManager am = (ActivityManager)
                 mContext.getSystemService(Context.ACTIVITY_SERVICE);
-
-        mHandler = new Handler();
     }
 
     public void setRecentsPanel(RecentsPanelView recentsPanel) {
@@ -225,8 +222,6 @@
         cancelLoadingThumbnailsAndIcons();
         final LinkedBlockingQueue<TaskDescription> tasksWaitingForThumbnails =
                 new LinkedBlockingQueue<TaskDescription>();
-        final ArrayList<TaskDescription> taskDescriptionsWaitingToLoad =
-                new ArrayList<TaskDescription>();
         mTaskLoader = new AsyncTask<Void, ArrayList<TaskDescription>, Void>() {
             @Override
             protected void onProgressUpdate(ArrayList<TaskDescription>... values) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index f85007e..e9c2ecb7 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -27,10 +27,6 @@
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 0bdf84a..cb69660 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -21,6 +21,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
+import android.app.TaskStackBuilder;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -845,8 +846,9 @@
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        getContext().startActivity(intent);
+        intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
+        TaskStackBuilder.create(getContext())
+                .addNextIntentWithParentStack(intent).startActivities();
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
index 9bc54cb..71cc1e4 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recent;
 
-import android.animation.LayoutTransition;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -24,11 +23,9 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
@@ -37,13 +34,10 @@
     public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true;
     public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true;
     private View mScrollView;
-    private RecentsCallback mCallback;
 
     private int mFadingEdgeLength;
-    private Context mContext;
     private boolean mIsVertical;
     private boolean mSoftwareRendered = false;
-    private boolean mAttachedToWindow = false;
 
     public static RecentsScrollViewPerformanceHelper create(Context context,
             AttributeSet attrs, View scrollView, boolean isVertical) {
@@ -59,7 +53,6 @@
     public RecentsScrollViewPerformanceHelper(Context context,
             AttributeSet attrs, View scrollView, boolean isVertical) {
         mScrollView = scrollView;
-        mContext = context;
         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View);
         mFadingEdgeLength = a.getDimensionPixelSize(android.R.styleable.View_fadingEdgeLength,
                 ViewConfiguration.get(context).getScaledFadingEdgeLength());
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index e802985..ba08775 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -27,10 +27,6 @@
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9448bbf..f25ac0d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -38,7 +38,6 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
-import android.graphics.RectF;
 import android.media.MediaActionSound;
 import android.net.Uri;
 import android.os.AsyncTask;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1204a89..b392648 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -16,12 +16,24 @@
 
 package com.android.systemui.statusbar;
 
-import java.util.ArrayList;
+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;
+import com.android.systemui.SystemUI;
+import com.android.systemui.recent.RecentTasksLoader;
+import com.android.systemui.recent.RecentsPanelView;
+import com.android.systemui.recent.TaskDescription;
+import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
 
 import android.app.ActivityManagerNative;
 import android.app.KeyguardManager;
-import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -51,25 +63,10 @@
 import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.RemoteViews;
 import android.widget.PopupMenu;
+import android.widget.RemoteViews;
 
-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.SearchPanelView;
-import com.android.systemui.SystemUI;
-import com.android.systemui.recent.RecentsPanelView;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.TaskDescription;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
-import com.android.systemui.statusbar.tablet.StatusBarPanel;
-
-import com.android.systemui.R;
+import java.util.ArrayList;
 
 public abstract class BaseStatusBar extends SystemUI implements
     CommandQueue.Callbacks, RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
@@ -301,8 +298,8 @@
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(intent);
+        intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
+        TaskStackBuilder.create(mContext).addNextIntentWithParentStack(intent).startActivities();
     }
 
     protected View.OnLongClickListener getNotificationLongClicker() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
new file mode 100755
index 0000000..81a16ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import java.io.BufferedWriter;
+import java.io.FileDescriptor;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.MotionEvent;
+
+/**
+ * Convenience class for capturing gestures for later analysis.
+ */
+public class GestureRecorder {
+    public static final boolean DEBUG = true; // for now
+    public static final String TAG = GestureRecorder.class.getSimpleName();
+
+    public class Gesture {
+        public abstract class Record {
+            long time;
+            public abstract String toJson();
+        }
+        public class MotionEventRecord extends Record {
+            public MotionEvent event;
+            public MotionEventRecord(long when, MotionEvent event) {
+                this.time = when;
+                this.event = event.copy();
+            }
+            String actionName(int action) {
+                switch (action) {
+                    case MotionEvent.ACTION_DOWN:
+                        return "down";
+                    case MotionEvent.ACTION_UP:
+                        return "up";
+                    case MotionEvent.ACTION_MOVE:
+                        return "move";
+                    case MotionEvent.ACTION_CANCEL:
+                        return "cancel";
+                    default:
+                        return String.valueOf(action);
+                }
+            }
+            public String toJson() {
+                return String.format(
+                        ("{\"type\":\"motion\", \"time\":%d, \"action\":\"%s\", "
+                            + "\"x\":%.2f, \"y\":%.2f, \"s\":%.2f, \"p\":%.2f}"),
+                        this.time,
+                        actionName(this.event.getAction()),
+                        this.event.getRawX(),
+                        this.event.getRawY(),
+                        this.event.getSize(),
+                        this.event.getPressure()
+                        );
+            }
+        }
+        public class TagRecord extends Record {
+            public String tag, info;
+            public TagRecord(long when, String tag, String info) {
+                this.time = when;
+                this.tag = tag;
+                this.info = info;
+            }
+            public String toJson() {
+                return String.format("{\"type\":\"tag\", \"time\":%d, \"tag\":\"%s\", \"info\":\"%s\"}",
+                        this.time,
+                        this.tag,
+                        this.info
+                        );
+            }
+        }
+        private LinkedList<Record> mRecords = new LinkedList<Record>();
+        private HashSet<String> mTags = new HashSet<String>();
+        long mDownTime = -1;
+        boolean mComplete = false;
+
+        public void add(MotionEvent ev) {
+            mRecords.add(new MotionEventRecord(ev.getEventTime(), ev));
+            if (mDownTime < 0) {
+                mDownTime = ev.getDownTime();
+            } else {
+                if (mDownTime != ev.getDownTime()) {
+                    // TODO: remove
+                    throw new RuntimeException("Assertion failure in GestureRecorder: event downTime ("
+                            +ev.getDownTime()+") does not match gesture downTime ("+mDownTime+")");
+                }
+            }
+            switch (ev.getActionMasked()) {
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    mComplete = true;
+            }
+        }
+        public void tag(long when, String tag, String info) {
+            mRecords.add(new TagRecord(when, tag, info));
+            mTags.add(tag);
+        }
+        public boolean isComplete() {
+            return mComplete;
+        }
+        public String toJson() {
+            StringBuilder sb = new StringBuilder();
+            boolean first = true;
+            sb.append("[");
+            for (Record r : mRecords) {
+                if (!first) sb.append(", ");
+                first = false;
+                sb.append(r.toJson());
+            }
+            sb.append("]");
+            return sb.toString();
+        }
+    }
+
+    // -=-=-=-=-=-=-=-=-=-=-=-
+
+    static final long SAVE_DELAY = 5000; // ms
+    static final int SAVE_MESSAGE = 6351;
+
+    private LinkedList<Gesture> mGestures;
+    private Gesture mCurrentGesture;
+    private int mLastSaveLen = -1;
+    private String mLogfile;
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == SAVE_MESSAGE) {
+                save();
+            }
+        }
+    };
+
+    public GestureRecorder(String filename) {
+        mLogfile = filename;
+        mGestures = new LinkedList<Gesture>();
+        mCurrentGesture = null;
+    }
+
+    public void add(MotionEvent ev) {
+        synchronized (mGestures) {
+            if (mCurrentGesture == null || mCurrentGesture.isComplete()) {
+                mCurrentGesture = new Gesture();
+                mGestures.add(mCurrentGesture);
+            }
+            mCurrentGesture.add(ev);
+        }
+        saveLater();
+    }
+
+    public void tag(long when, String tag, String info) {
+        synchronized (mGestures) {
+            if (mCurrentGesture == null) {
+                mCurrentGesture = new Gesture();
+                mGestures.add(mCurrentGesture);
+            }
+            mCurrentGesture.tag(when, tag, info);
+        }
+        saveLater();
+    }
+
+    public void tag(long when, String tag) {
+        tag(when, tag, null);
+    }
+
+    public void tag(String tag) {
+        tag(SystemClock.uptimeMillis(), tag, null);
+    }
+
+    public void tag(String tag, String info) {
+        tag(SystemClock.uptimeMillis(), tag, info);
+    }
+
+    /**
+     * Generates a JSON string capturing all completed gestures.
+     * Not threadsafe; call with a lock.
+     */
+    public String toJsonLocked() {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        sb.append("[");
+        int count = 0;
+        for (Gesture g : mGestures) {
+            if (!g.isComplete()) continue;
+            if (!first) sb.append("," );
+            first = false;
+            sb.append(g.toJson());
+            count++;
+        }
+        mLastSaveLen = count;
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public String toJson() {
+        String s;
+        synchronized (mGestures) {
+            s = toJsonLocked();
+        }
+        return s;
+    }
+
+    public void saveLater() {
+        mHandler.removeMessages(SAVE_MESSAGE);
+        mHandler.sendEmptyMessageDelayed(SAVE_MESSAGE, SAVE_DELAY);
+    }
+
+    public void save() {
+        synchronized (mGestures) {
+            try {
+                BufferedWriter w = new BufferedWriter(new FileWriter(mLogfile, /*append=*/ true));
+                w.append(toJsonLocked() + "\n");
+                w.close();
+                mGestures.clear();
+                // If we have a pending gesture, push it back
+                if (mCurrentGesture != null && !mCurrentGesture.isComplete()) {
+                    mGestures.add(mCurrentGesture);
+                }
+                if (DEBUG) {
+                    Slog.v(TAG, String.format("Wrote %d complete gestures to %s", mLastSaveLen, mLogfile));
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, String.format("Couldn't write gestures to %s", mLogfile), e);
+                mLastSaveLen = -1;
+            }
+        }
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        save();
+        if (mLastSaveLen >= 0) {
+            pw.println(String.valueOf(mLastSaveLen) + " gestures written to " + mLogfile);
+        } else {
+            pw.println("error writing gestures");
+        }
+    }
+}
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 c337ebe..25de109 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -72,14 +71,17 @@
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 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.UniverseBackground;
 import com.android.systemui.recent.RecentTasksLoader;
 import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.RotationToggle;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
@@ -87,9 +89,9 @@
 import com.android.systemui.statusbar.policy.DateView;
 import com.android.systemui.statusbar.policy.IntruderAlertView;
 import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.OnSizeChangedListener;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.policy.OnSizeChangedListener;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -154,6 +156,8 @@
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
 
+    UniverseBackground mUniverseBackground;
+
     int mPixelFormat;
     Object mQueueLock = new Object();
 
@@ -239,6 +243,9 @@
 
     DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
+    // XXX: gesture research
+    private GestureRecorder mGestureRec = new GestureRecorder("/sdcard/statusbar_gestures.dat");
+
     private int mNavigationIconHints = 0;
     private final Animator.AnimatorListener mMakeIconsInvisible = new AnimatorListenerAdapter() {
         @Override
@@ -285,25 +292,6 @@
         }
     };
 
-    private class ExpandedDialog extends Dialog {
-        ExpandedDialog(Context context) {
-            super(context, com.android.internal.R.style.Theme_Translucent_NoTitleBar);
-        }
-
-        @Override
-        public boolean dispatchKeyEvent(KeyEvent event) {
-            boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
-            switch (event.getKeyCode()) {
-            case KeyEvent.KEYCODE_BACK:
-                if (!down) {
-                    animateCollapse();
-                }
-                return true;
-            }
-            return super.dispatchKeyEvent(event);
-        }
-    }
-
     @Override
     public void start() {
         mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
@@ -318,6 +306,11 @@
 
         if (ENABLE_INTRUDERS) addIntruderView();
 
+        mUniverseBackground = new UniverseBackground(mContext);
+        mUniverseBackground.setVisibility(View.GONE);
+        WindowManagerImpl.getDefault().addView(mUniverseBackground,
+                mUniverseBackground.getLayoutParams(mDisplay));
+
         // Lastly, call to the icon policy to install/update all the icons.
         mIconPolicy = new PhoneStatusBarPolicy(mContext);
     }
@@ -672,8 +665,6 @@
     }
 
     private void addIntruderView() {
-        final int height = getStatusBarHeight();
-
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -858,12 +849,6 @@
         mSettingsButton.setEnabled(isDeviceProvisioned());
     }
 
-    private void reloadAllNotificationIcons() {
-        if (mNotificationIcons == null) return;
-        mNotificationIcons.removeAllViews();
-        updateNotificationIcons();
-    }
-
     @Override
     protected void updateNotificationIcons() {
         if (mNotificationIcons == null) return;
@@ -1556,6 +1541,26 @@
         stopTracking();
     }
 
+    boolean handleUniverseEvent(MotionEvent event) {
+        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
+            return false;
+        }
+        if (mExpanded) {
+            return false;
+        }
+        if (mUniverseBackground.consumeEvent(event)) {
+            if (mTracking) {
+                // fling back to the top, starting from the last tracked position.
+                mFlingY = mTrackingPosition;
+                mViewDelta = 0;
+                mFlingVelocity = -1;
+                mHandler.post(mPerformFling);
+            }
+            return true;
+        }
+        return false;
+    }
+
     boolean interceptTouchEvent(MotionEvent event) {
         if (SPEW) {
             Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
@@ -1569,14 +1574,16 @@
             }
         }
 
+        mGestureRec.add(event);
+
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
             return false;
         }
 
+        final int y = (int)event.getRawY();
         final int action = event.getAction();
         final int statusBarSize = getStatusBarHeight();
         final int hitSize = statusBarSize*2;
-        final int y = (int)event.getRawY();
         if (action == MotionEvent.ACTION_DOWN) {
             if (!areLightsOn()) {
                 setLightsOn(true);
@@ -1603,6 +1610,7 @@
                 if (x >= edgeBorder && x < mDisplayMetrics.widthPixels - edgeBorder) {
                     prepareTracking(y, !mExpanded);// opening if we're not already fully visible
                     trackMovement(event);
+                    mGestureRec.tag("tracking", mExpanded ? "expanded" : "collapsed");
                 }
             }
         } else if (mTracking) {
@@ -1653,6 +1661,8 @@
                     mFlingY = y;
                 }
                 mFlingVelocity = vel;
+                mGestureRec.tag("fling " + ((mFlingVelocity > 0) ? "open" : "closed"),
+                                "v=" + mFlingVelocity);
                 mHandler.post(mPerformFling);
             }
 
@@ -1793,64 +1803,6 @@
     @Override
     public void setHardKeyboardStatus(boolean available, boolean enabled) { }
 
-    private class NotificationClicker implements View.OnClickListener {
-        private PendingIntent mIntent;
-        private String mPkg;
-        private String mTag;
-        private int mId;
-
-        NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
-            mIntent = intent;
-            mPkg = pkg;
-            mTag = tag;
-            mId = id;
-        }
-
-        public void onClick(View v) {
-            try {
-                // The intent we are sending is for the application, which
-                // won't have permission to immediately start an activity after
-                // the user switches to home.  We know it is safe to do at this
-                // point, so make sure new activity switches are now allowed.
-                ActivityManagerNative.getDefault().resumeAppSwitches();
-                // Also, notifications can be launched from the lock screen,
-                // so dismiss the lock screen when the activity starts.
-                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-            } catch (RemoteException e) {
-            }
-
-            if (mIntent != null) {
-                int[] pos = new int[2];
-                v.getLocationOnScreen(pos);
-                Intent overlay = new Intent();
-                overlay.setSourceBounds(
-                        new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
-                try {
-                    mIntent.send(mContext, 0, overlay);
-                } catch (PendingIntent.CanceledException e) {
-                    // the stack trace isn't very helpful here.  Just log the exception message.
-                    Slog.w(TAG, "Sending contentIntent failed: " + e);
-                }
-
-                KeyguardManager kgm =
-                    (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
-                if (kgm != null) kgm.exitKeyguardSecurely(null);
-            }
-
-            try {
-                mBarService.onNotificationClick(mPkg, mTag, mId);
-            } catch (RemoteException ex) {
-                // system process is dead if we're here.
-            }
-
-            // close the shade if it was open
-            animateCollapse();
-
-            // If this click was on the intruder alert, hide that instead
-            mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
-        }
-    }
-
     @Override
     protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
         // no ticking in lights-out mode
@@ -1995,6 +1947,9 @@
             }
         }
 
+        pw.print("  status bar gestures: ");
+        mGestureRec.dump(fd, pw, args);
+
         mNetworkController.dump(fd, pw, args);
     }
 
@@ -2076,7 +2031,6 @@
         }
 
         // tracking view...
-        int pos;
         if (expandedPosition == EXPANDED_FULL_OPEN) {
             panelh = disph;
         }
@@ -2171,9 +2125,6 @@
     }
 
     private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
-        final int mini(int a, int b) {
-            return (b>a?a:b);
-        }
         public void onClick(View v) {
             synchronized (mNotificationData) {
                 // animate-swipe all dismissable notifications, then animate the shade closed
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index a9cc62a4d6..fd4cff8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -22,6 +22,7 @@
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 9317561..f53ed0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -37,6 +37,8 @@
     private ExpandHelper mExpandHelper;
     private NotificationRowLayout latestItems;
 
+    private boolean mUniverseHandling = false;
+
     PhoneStatusBar mService;
 
     public StatusBarWindowView(Context context, AttributeSet attrs) {
@@ -53,6 +55,7 @@
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
+        mExpandHelper.setScrollView(scroller);
     }
 
     @Override
@@ -70,19 +73,35 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        MotionEvent cancellation = MotionEvent.obtain(ev);
-        cancellation.setAction(MotionEvent.ACTION_CANCEL);
+        if (mService.handleUniverseEvent(ev)) {
+            mUniverseHandling = true;
+            MotionEvent cancellation = MotionEvent.obtain(ev);
+            cancellation.setAction(MotionEvent.ACTION_CANCEL);
+            mExpandHelper.onInterceptTouchEvent(cancellation);
+            latestItems.onInterceptTouchEvent(cancellation);
+            cancellation.recycle();
+            return true;
+        }
 
         boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) ||
                 super.onInterceptTouchEvent(ev);
         if (intercept) {
+            MotionEvent cancellation = MotionEvent.obtain(ev);
+            cancellation.setAction(MotionEvent.ACTION_CANCEL);
             latestItems.onInterceptTouchEvent(cancellation);
+            cancellation.recycle();
         }
         return intercept;
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
+        if (mUniverseHandling) {
+            if (!mService.handleUniverseEvent(ev)) {
+                mUniverseHandling = false;
+            }
+            return true;
+        }
         boolean handled = mExpandHelper.onTouchEvent(ev) ||
                 super.onTouchEvent(ev);
         return handled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 61e5ab6..a10b6c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -204,6 +204,20 @@
         return null;
     }
 
+    public View getPreviousChild(View currentChild) {
+        final int count = getChildCount();
+        for (int childIdx = 0; childIdx < count; childIdx++) {
+            if (getChildAt(childIdx) == currentChild) {
+                if (childIdx == 0) {
+                    return null;
+                } else {
+                    return getChildAt(childIdx - 1);
+                }
+            }
+        }
+        return null;
+    }
+
     public View getChildContentView(View v) {
         return v;
     }
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 f947369..cbd8831 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -57,7 +57,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.RemoteViews;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
@@ -70,9 +69,9 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DoNotDisturb;
 import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CompatModeButton;
@@ -232,10 +231,7 @@
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                // We use a pixel format of RGB565 for the status bar to save memory bandwidth and
-                // to ensure that the layer can be handled by HWComposer.  On some devices the
-                // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
-                PixelFormat.RGB_565);
+                PixelFormat.OPAQUE);
 
         // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
         // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
@@ -495,8 +491,7 @@
         // where the icons go
         mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
 
-        ViewConfiguration vc = ViewConfiguration.get(context);
-        mNotificationPeekTapDuration = vc.getTapTimeout();
+        mNotificationPeekTapDuration = ViewConfiguration.getTapTimeout();
         mNotificationFlingVelocity = 300; // px/s
 
         mTicker = new TabletTicker(this);
@@ -1294,7 +1289,7 @@
                 mNotificationArea.postDelayed(mHiliteOnR, 100);
             } else {
                 mNotificationArea.removeCallbacks(mHiliteOnR);
-                mNotificationArea.setBackgroundDrawable(null);
+                mNotificationArea.setBackground(null);
             }
         }
 
@@ -1368,106 +1363,6 @@
                 NOTIFICATION_PEEK_FADE_DELAY);
     }
 
-    private class NotificationIconTouchListener implements View.OnTouchListener {
-        VelocityTracker mVT;
-        int mPeekIndex;
-        float mInitialTouchX, mInitialTouchY;
-        int mTouchSlop;
-
-        public NotificationIconTouchListener() {
-            mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
-        }
-
-        public boolean onTouch(View v, MotionEvent event) {
-            boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
-            boolean panelShowing = mNotificationPanel.isShowing();
-            if (panelShowing) return false;
-
-            int numIcons = mIconLayout.getChildCount();
-            int newPeekIndex = (int)(event.getX() * numIcons / mIconLayout.getWidth());
-            if (newPeekIndex > numIcons - 1) newPeekIndex = numIcons - 1;
-            else if (newPeekIndex < 0) newPeekIndex = 0;
-
-            final int action = event.getAction();
-            switch (action) {
-                case MotionEvent.ACTION_DOWN:
-                    mVT = VelocityTracker.obtain();
-                    mInitialTouchX = event.getX();
-                    mInitialTouchY = event.getY();
-                    mPeekIndex = -1;
-
-                    // fall through
-                case MotionEvent.ACTION_OUTSIDE:
-                case MotionEvent.ACTION_MOVE:
-                    // peek and switch icons if necessary
-
-                    if (newPeekIndex != mPeekIndex) {
-                        mPeekIndex = newPeekIndex;
-
-                        if (DEBUG) Slog.d(TAG, "will peek at notification #" + mPeekIndex);
-                        Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
-                        peekMsg.arg1 = mPeekIndex;
-
-                        mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-
-                        if (peeking) {
-                            // no delay if we're scrubbing left-right
-                            mHandler.sendMessage(peekMsg);
-                        } else {
-                            // wait for fling
-                            mHandler.sendMessageDelayed(peekMsg, NOTIFICATION_PEEK_HOLD_THRESH);
-                        }
-                    }
-
-                    // check for fling
-                    if (mVT != null) {
-                        mVT.addMovement(event);
-                        mVT.computeCurrentVelocity(1000); // pixels per second
-                        // require a little more oomph once we're already in peekaboo mode
-                        if (!panelShowing && (
-                               (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
-                            || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
-                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
-                            mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
-                            mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
-                        }
-                    }
-                    return true;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-                    if (!peeking) {
-                        if (action == MotionEvent.ACTION_UP
-                                // was this a sloppy tap?
-                                && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
-                                && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
-                                // dragging off the bottom doesn't count
-                                && (int)event.getY() < v.getBottom()) {
-                            Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
-                            peekMsg.arg1 = mPeekIndex;
-                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-                            mHandler.sendMessage(peekMsg);
-
-                            v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                            v.playSoundEffect(SoundEffectConstants.CLICK);
-
-                            peeking = true; // not technically true yet, but the next line will run
-                        }
-                    }
-
-                    if (peeking) {
-                        resetNotificationPeekFadeTimer();
-                    }
-
-                    mVT.recycle();
-                    mVT = null;
-                    return true;
-            }
-            return false;
-        }
-    }
-
     private void reloadAllNotificationIcons() {
         if (mIconLayout == null) return;
         mIconLayout.removeAllViews();
@@ -1609,9 +1504,9 @@
         if (!(bgd instanceof LayerDrawable)) return;
 
         LayerDrawable d = (LayerDrawable) bgd;
-        v.setBackgroundDrawable(null);
+        v.setBackground(null);
         d.setOpacity(PixelFormat.TRANSLUCENT);
-        v.setBackgroundDrawable(d);
+        v.setBackground(d);
     }
 
     public void clearAll() {
diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml
index 7bd5590..ec163af 100644
--- a/packages/VpnDialogs/res/values-fa/strings.xml
+++ b/packages/VpnDialogs/res/values-fa/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="8359175999006833462">"<xliff:g id="APP">%s</xliff:g> تلاش می‌کند یک اتصال VPN ایجاد کند."</string>
-    <string name="warning" msgid="5470743576660160079">"با ادامه دادن، به برنامه کاربردی اجازه می‌دهید تمام ترافیک شبکه را رهگیری کند. "<b>"تا به برنامه اعتماد نکردید آن را قبول نکنید."</b>" در غیر این صورت، این ریسک را قبول می‌کنید که داده‌های شما توسط یک نرم‌افزار مخرب به خطر بیفتد."</string>
+    <string name="warning" msgid="5470743576660160079">"با ادامه دادن، به برنامهٔ کاربردی اجازه می‌دهید تمام ترافیک شبکه را رهگیری کند. "<b>"تا به برنامه اعتماد نکردید آن را قبول نکنید."</b>" در غیر این صورت، این ریسک را قبول می‌کنید که داده‌های شما توسط یک نرم‌افزار مخرب به خطر بیفتد."</string>
     <string name="accept" msgid="2889226408765810173">"من به این برنامه اعتماد دارم."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN متصل است"</string>
     <string name="configure" msgid="4905518375574791375">"پیکربندی"</string>
diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml
index c9710e5..2848f83 100644
--- a/packages/VpnDialogs/res/values-in/strings.xml
+++ b/packages/VpnDialogs/res/values-in/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="8359175999006833462">"<xliff:g id="APP">%s</xliff:g> mencoba membuat sambungan VPN."</string>
-    <string name="warning" msgid="5470743576660160079">"Dengan melanjutkan, Anda memberikan izin kepada aplikasi untuk mencegat semua lalu lintas jaringan. "<b>"JANGAN memberi izin kecuali Anda mempercayai aplikasi ini."</b>" Jika tidak, data Anda berisiko disusupi oleh perangkat lunak jahat."</string>
+    <string name="warning" msgid="5470743576660160079">"Dengan melanjutkan, Anda memberikan izin kepada aplikasi untuk mencegat semua lalu lintas jaringan. "<b>"JANGAN memberi izin kecuali Anda mempercayai aplikasi ini."</b>" Jika tidak, data Anda berisiko disusupi oleh perangkat lunak perusak."</string>
     <string name="accept" msgid="2889226408765810173">"Saya mempercayai aplikasi ini."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string>
     <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string>
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index fc187ce..e9b8267 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -29,6 +29,8 @@
 import android.content.IntentFilter;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ScaleDrawable;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.os.Handler;
@@ -43,6 +45,7 @@
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.IWindowManager;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -52,6 +55,7 @@
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
 
 import java.util.ArrayList;
@@ -243,8 +247,10 @@
             for (final UserInfo user : users) {
                 boolean isCurrentUser = currentUser == null
                         ? user.id == 0 : (currentUser.id == user.id);
+                Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath)
+                        : null;
                 SinglePressAction switchToUser = new SinglePressAction(
-                        com.android.internal.R.drawable.ic_menu_cc,
+                        com.android.internal.R.drawable.ic_menu_cc, icon,
                         (user.name != null ? user.name : "Primary")
                         + (isCurrentUser ? " \u2714" : "")) {
                     public void onPress() {
@@ -439,6 +445,7 @@
      */
     private static abstract class SinglePressAction implements Action {
         private final int mIconResId;
+        private final Drawable mIcon;
         private final int mMessageResId;
         private final CharSequence mMessage;
 
@@ -446,13 +453,23 @@
             mIconResId = iconResId;
             mMessageResId = messageResId;
             mMessage = null;
+            mIcon = null;
+        }
+
+        protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
+            mIconResId = iconResId;
+            mMessageResId = 0;
+            mMessage = message;
+            mIcon = icon;
         }
 
         protected SinglePressAction(int iconResId, CharSequence message) {
             mIconResId = iconResId;
             mMessageResId = 0;
             mMessage = message;
+            mIcon = null;
         }
+
         public boolean isEnabled() {
             return true;
         }
@@ -471,8 +488,12 @@
             TextView messageView = (TextView) v.findViewById(R.id.message);
 
             v.findViewById(R.id.status).setVisibility(View.GONE);
-
-            icon.setImageDrawable(context.getResources().getDrawable(mIconResId));
+            if (mIcon != null) {
+                icon.setImageDrawable(mIcon);
+                icon.setScaleType(ScaleType.CENTER_CROP);
+            } else if (mIconResId != 0) {
+                icon.setImageDrawable(context.getResources().getDrawable(mIconResId));
+            }
             if (mMessage != null) {
                 messageView.setText(mMessage);
             } else {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index c1fd515..bb07a1d 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -21,8 +21,7 @@
 import com.android.internal.widget.DigitalClock;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.TransportControlView;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
+import com.android.internal.policy.impl.KeyguardUpdateMonitor.BatteryStatus;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -107,6 +106,8 @@
     private CharSequence mSpn;
     protected int mPhoneState;
     private DigitalClock mDigitalClock;
+    protected boolean mBatteryCharged;
+    protected boolean mBatteryIsLow;
 
     private class TransientTextManager {
         private TextView mTextView;
@@ -198,8 +199,8 @@
 
         mTransientTextManager = new TransientTextManager(mCarrierView);
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+        // Registering this callback immediately updates the battery state, among other things.
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         resetStatusInfo();
         refreshDate();
@@ -287,7 +288,6 @@
     public void onPause() {
         if (DEBUG) Log.v(TAG, "onPause()");
         mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
     }
 
     /** {@inheritDoc} */
@@ -299,8 +299,7 @@
             mDigitalClock.updateTime();
         }
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+        mUpdateMonitor.registerCallback(mInfoCallback);
         resetStatusInfo();
         // Issue the biometric unlock failure message in a centralized place
         // TODO: we either need to make the Face Unlock multiple failures string a more general
@@ -312,9 +311,6 @@
 
     void resetStatusInfo() {
         mInstructionText = null;
-        mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
-        mBatteryLevel = mUpdateMonitor.getBatteryLevel();
         updateStatusLines(true);
     }
 
@@ -379,14 +375,11 @@
         if (mShowingBatteryInfo) {
             // Battery status
             if (mPluggedIn) {
-                // Charging or charged
-                if (mUpdateMonitor.isDeviceCharged()) {
-                    string = getContext().getString(R.string.lockscreen_charged);
-                } else {
-                    string = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
-                }
+                // Charging, charged or waiting to charge.
+                string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
+                        :R.string.lockscreen_plugged_in, mBatteryLevel);
                 icon.value = CHARGING_ICON;
-            } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+            } else if (mBatteryIsLow) {
                 // Battery is low
                 string = getContext().getString(R.string.lockscreen_low_battery);
                 icon.value = BATTERY_LOW_ICON;
@@ -406,14 +399,11 @@
         } else if (mShowingBatteryInfo) {
             // Battery status
             if (mPluggedIn) {
-                // Charging or charged
-                if (mUpdateMonitor.isDeviceCharged()) {
-                    string = getContext().getString(R.string.lockscreen_charged);
-                } else {
-                    string = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
-                }
+                // Charging, charged or waiting to charge.
+                string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
+                        :R.string.lockscreen_plugged_in, mBatteryLevel);
                 icon.value = CHARGING_ICON;
-            } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+            } else if (mBatteryIsLow) {
                 // Battery is low
                 string = getContext().getString(R.string.lockscreen_low_battery);
                 icon.value = BATTERY_LOW_ICON;
@@ -629,14 +619,15 @@
         }
     }
 
-    private InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-            mShowingBatteryInfo = showBatteryInfo;
-            mPluggedIn = pluggedIn;
-            mBatteryLevel = batteryLevel;
+        public void onRefreshBatteryInfo(BatteryStatus status) {
+            mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow();
+            mPluggedIn = status.isPluggedIn();
+            mBatteryLevel = status.level;
+            mBatteryCharged = status.isCharged();
+            mBatteryIsLow = status.isBatteryLow();
             final MutableInt tmpIcon = new MutableInt(0);
             update(BATTERY_INFO, getAltTextMessage(tmpIcon));
         }
@@ -659,10 +650,7 @@
             updateEmergencyCallButtonState(phoneState);
         }
 
-    };
-
-    private SimStateCallback mSimStateCallback = new SimStateCallback() {
-
+        @Override
         public void onSimStateChanged(IccCardConstants.State simState) {
             updateCarrierStateWithSimStatus(simState);
         }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 5cd0349..a939222 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -57,37 +57,13 @@
  */
 public class KeyguardUpdateMonitor {
 
-    static private final String TAG = "KeyguardUpdateMonitor";
-    static private final boolean DEBUG = false;
-
-    /* package */ static final int LOW_BATTERY_THRESHOLD = 20;
-
-    private final Context mContext;
-
-    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
-
-    private boolean mDeviceProvisioned;
-
-    private BatteryStatus mBatteryStatus;
-
-    private CharSequence mTelephonyPlmn;
-    private CharSequence mTelephonySpn;
-
-    private int mFailedAttempts = 0;
-    private int mFailedBiometricUnlockAttempts = 0;
+    private static final String TAG = "KeyguardUpdateMonitor";
+    private static final boolean DEBUG = false;
+    private static final boolean DEBUG_SIM_STATES = DEBUG || false;
     private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
+    private static final int LOW_BATTERY_THRESHOLD = 20;
 
-    private boolean mClockVisible;
-
-    private Handler mHandler;
-
-    private ArrayList<InfoCallback> mInfoCallbacks = Lists.newArrayList();
-    private ArrayList<SimStateCallback> mSimStateCallbacks = Lists.newArrayList();
-    private ContentObserver mContentObserver;
-    private int mRingMode;
-    private int mPhoneState;
-
-    // messages for the handler
+    // Callback messages
     private static final int MSG_TIME_UPDATE = 301;
     private static final int MSG_BATTERY_UPDATE = 302;
     private static final int MSG_CARRIER_INFO_UPDATE = 303;
@@ -97,9 +73,118 @@
     private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
     private static final int MSG_DEVICE_PROVISIONED = 308;
     protected static final int MSG_DPM_STATE_CHANGED = 309;
-    protected static final int MSG_USER_CHANGED = 310;
+    protected static final int MSG_USER_SWITCHED = 310;
+    protected static final int MSG_USER_REMOVED = 311;
 
-    protected static final boolean DEBUG_SIM_STATES = DEBUG || false;
+    private final Context mContext;
+
+    // Telephony state
+    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    private CharSequence mTelephonyPlmn;
+    private CharSequence mTelephonySpn;
+    private int mRingMode;
+    private int mPhoneState;
+
+    private boolean mDeviceProvisioned;
+
+    private BatteryStatus mBatteryStatus;
+
+    private int mFailedAttempts = 0;
+    private int mFailedBiometricUnlockAttempts = 0;
+
+    private boolean mClockVisible;
+
+    private ArrayList<KeyguardUpdateMonitorCallback> mCallbacks = Lists.newArrayList();
+    private ContentObserver mContentObserver;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_TIME_UPDATE:
+                    handleTimeUpdate();
+                    break;
+                case MSG_BATTERY_UPDATE:
+                    handleBatteryUpdate((BatteryStatus) msg.obj);
+                    break;
+                case MSG_CARRIER_INFO_UPDATE:
+                    handleCarrierInfoUpdate();
+                    break;
+                case MSG_SIM_STATE_CHANGE:
+                    handleSimStateChange((SimArgs) msg.obj);
+                    break;
+                case MSG_RINGER_MODE_CHANGED:
+                    handleRingerModeChange(msg.arg1);
+                    break;
+                case MSG_PHONE_STATE_CHANGED:
+                    handlePhoneStateChanged((String)msg.obj);
+                    break;
+                case MSG_CLOCK_VISIBILITY_CHANGED:
+                    handleClockVisibilityChanged();
+                    break;
+                case MSG_DEVICE_PROVISIONED:
+                    handleDeviceProvisioned();
+                    break;
+                case MSG_DPM_STATE_CHANGED:
+                    handleDevicePolicyManagerStateChanged();
+                    break;
+                case MSG_USER_SWITCHED:
+                    handleUserSwitched(msg.arg1);
+                    break;
+                case MSG_USER_REMOVED:
+                    handleUserRemoved(msg.arg1);
+                    break;
+            }
+        }
+    };
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (DEBUG) Log.d(TAG, "received broadcast " + action);
+
+            if (Intent.ACTION_TIME_TICK.equals(action)
+                    || Intent.ACTION_TIME_CHANGED.equals(action)
+                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
+            } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
+                mTelephonyPlmn = getTelephonyPlmnFrom(intent);
+                mTelephonySpn = getTelephonySpnFrom(intent);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
+            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+                final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
+                final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
+                final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
+                final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
+                final Message msg = mHandler.obtainMessage(
+                        MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
+                mHandler.sendMessage(msg);
+            } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+                if (DEBUG_SIM_STATES) {
+                    Log.v(TAG, "action " + action + " state" +
+                        intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
+                }
+                mHandler.sendMessage(mHandler.obtainMessage(
+                        MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
+            } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
+                        intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
+            } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
+                String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
+            } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+                    .equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
+            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+                        intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
+                        intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
+            }
+        }
+    };
 
     /**
      * When we receive a
@@ -156,7 +241,7 @@
         }
     }
 
-    private static class BatteryStatus {
+    /* package */ static class BatteryStatus {
         public final int status;
         public final int level;
         public final int plugged;
@@ -168,91 +253,53 @@
             this.health = health;
         }
 
+        /**
+         * Determine whether the device is plugged in (USB or power).
+         * @return true if the device is plugged in.
+         */
+        boolean isPluggedIn() {
+            return plugged == BatteryManager.BATTERY_PLUGGED_AC
+                    || plugged == BatteryManager.BATTERY_PLUGGED_USB;
+        }
+
+        /**
+         * Whether or not the device is charged. Note that some devices never return 100% for
+         * battery level, so this allows either battery level or status to determine if the
+         * battery is charged.
+         * @return true if the device is charged
+         */
+        public boolean isCharged() {
+            return status == BATTERY_STATUS_FULL || level >= 100;
+        }
+
+        /**
+         * Whether battery is low and needs to be charged.
+         * @return true if battery is low
+         */
+        public boolean isBatteryLow() {
+            return level < LOW_BATTERY_THRESHOLD;
+        }
+
     }
 
     public KeyguardUpdateMonitor(Context context) {
         mContext = context;
 
-        mHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case MSG_TIME_UPDATE:
-                        handleTimeUpdate();
-                        break;
-                    case MSG_BATTERY_UPDATE:
-                        handleBatteryUpdate((BatteryStatus) msg.obj);
-                        break;
-                    case MSG_CARRIER_INFO_UPDATE:
-                        handleCarrierInfoUpdate();
-                        break;
-                    case MSG_SIM_STATE_CHANGE:
-                        handleSimStateChange((SimArgs) msg.obj);
-                        break;
-                    case MSG_RINGER_MODE_CHANGED:
-                        handleRingerModeChange(msg.arg1);
-                        break;
-                    case MSG_PHONE_STATE_CHANGED:
-                        handlePhoneStateChanged((String)msg.obj);
-                        break;
-                    case MSG_CLOCK_VISIBILITY_CHANGED:
-                        handleClockVisibilityChanged();
-                        break;
-                    case MSG_DEVICE_PROVISIONED:
-                        handleDeviceProvisioned();
-                        break;
-                    case MSG_DPM_STATE_CHANGED:
-                        handleDevicePolicyManagerStateChanged();
-                        break;
-                    case MSG_USER_CHANGED:
-                        handleUserChanged(msg.arg1);
-                        break;
-                }
-            }
-        };
-
         mDeviceProvisioned = Settings.Secure.getInt(
                 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
 
         // Since device can't be un-provisioned, we only need to register a content observer
         // to update mDeviceProvisioned when we are...
         if (!mDeviceProvisioned) {
-            mContentObserver = new ContentObserver(mHandler) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    super.onChange(selfChange);
-                    mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
-                    if (mDeviceProvisioned) {
-                        mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
-                    }
-                    if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
-                }
-            };
-
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED),
-                    false, mContentObserver);
-
-            // prevent a race condition between where we check the flag and where we register the
-            // observer by grabbing the value once again...
-            boolean provisioned = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
-            if (provisioned != mDeviceProvisioned) {
-                mDeviceProvisioned = provisioned;
-                if (mDeviceProvisioned) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
-                }
-            }
+            watchForDeviceProvisioning();
         }
 
-        // take a guess to start
-        mSimState = IccCardConstants.State.READY;
+        // Take a guess at initial SIM state, battery status and PLMN until we get an update
+        mSimState = IccCardConstants.State.NOT_READY;
         mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
-
         mTelephonyPlmn = getDefaultPlmn();
 
-        // setup receiver
+        // Watch for interesting updates
         final IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_TIME_TICK);
         filter.addAction(Intent.ACTION_TIME_CHANGED);
@@ -265,67 +312,72 @@
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_USER_REMOVED);
-        context.registerReceiver(new BroadcastReceiver() {
+        context.registerReceiver(mBroadcastReceiver, filter);
+    }
 
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                if (DEBUG) Log.d(TAG, "received broadcast " + action);
-
-                if (Intent.ACTION_TIME_TICK.equals(action)
-                        || Intent.ACTION_TIME_CHANGED.equals(action)
-                        || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
-                } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
-                    mTelephonyPlmn = getTelephonyPlmnFrom(intent);
-                    mTelephonySpn = getTelephonySpnFrom(intent);
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
-                } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
-                    final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
-                    final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
-                    final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
-                    final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
-                    final Message msg = mHandler.obtainMessage(
-                            MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
-                    mHandler.sendMessage(msg);
-                } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
-                    if (DEBUG_SIM_STATES) {
-                        Log.v(TAG, "action " + action + " state" +
-                            intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
-                    }
-                    mHandler.sendMessage(mHandler.obtainMessage(
-                            MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
-                } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
-                            intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
-                } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
-                    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
-                } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
-                        .equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
-                } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_CHANGED,
-                            intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
+    private void watchForDeviceProvisioning() {
+        mContentObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                super.onChange(selfChange);
+                mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
+                if (mDeviceProvisioned) {
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
                 }
+                if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
             }
-        }, filter);
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED),
+                false, mContentObserver);
+
+        // prevent a race condition between where we check the flag and where we register the
+        // observer by grabbing the value once again...
+        boolean provisioned = Settings.Secure.getInt(mContext.getContentResolver(),
+            Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
+        if (provisioned != mDeviceProvisioned) {
+            mDeviceProvisioned = provisioned;
+            if (mDeviceProvisioned) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
+            }
+        }
     }
 
+    /**
+     * Handle {@link #MSG_DPM_STATE_CHANGED}
+     */
     protected void handleDevicePolicyManagerStateChanged() {
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onDevicePolicyManagerStateChanged();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onDevicePolicyManagerStateChanged();
         }
     }
 
-    protected void handleUserChanged(int userId) {
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onUserChanged(userId);
+    /**
+     * Handle {@link #MSG_USER_SWITCHED}
+     */
+    protected void handleUserSwitched(int userId) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onUserSwitched(userId);
         }
     }
 
+    /**
+     * Handle {@link #MSG_USER_SWITCHED}
+     */
+    protected void handleUserRemoved(int userId) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onUserRemoved(userId);
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_DEVICE_PROVISIONED}
+     */
     protected void handleDeviceProvisioned() {
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onDeviceProvisioned();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onDeviceProvisioned();
         }
         if (mContentObserver != null) {
             // We don't need the observer anymore...
@@ -334,6 +386,9 @@
         }
     }
 
+    /**
+     * Handle {@link #MSG_PHONE_STATE_CHANGED}
+     */
     protected void handlePhoneStateChanged(String newState) {
         if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
         if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
@@ -343,16 +398,19 @@
         } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
             mPhoneState = TelephonyManager.CALL_STATE_RINGING;
         }
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onPhoneStateChanged(mPhoneState);
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onPhoneStateChanged(mPhoneState);
         }
     }
 
+    /**
+     * Handle {@link #MSG_RINGER_MODE_CHANGED}
+     */
     protected void handleRingerModeChange(int mode) {
         if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
         mRingMode = mode;
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onRingerModeChanged(mode);
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onRingerModeChanged(mode);
         }
     }
 
@@ -361,24 +419,21 @@
      */
     private void handleTimeUpdate() {
         if (DEBUG) Log.d(TAG, "handleTimeUpdate");
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onTimeChanged();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onTimeChanged();
         }
     }
 
     /**
      * Handle {@link #MSG_BATTERY_UPDATE}
      */
-    private void handleBatteryUpdate(BatteryStatus batteryStatus) {
+    private void handleBatteryUpdate(BatteryStatus status) {
         if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
-        final boolean batteryUpdateInteresting =
-                isBatteryUpdateInteresting(mBatteryStatus, batteryStatus);
-        mBatteryStatus = batteryStatus;
+        final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
+        mBatteryStatus = status;
         if (batteryUpdateInteresting) {
-            for (int i = 0; i < mInfoCallbacks.size(); i++) {
-                // TODO: pass BatteryStatus object to onRefreshBatteryInfo() instead...
-                mInfoCallbacks.get(i).onRefreshBatteryInfo(
-                    shouldShowBatteryInfo(),isPluggedIn(batteryStatus), batteryStatus.level);
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                mCallbacks.get(i).onRefreshBatteryInfo(status);
             }
         }
     }
@@ -390,8 +445,8 @@
         if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
             + ", spn = " + mTelephonySpn);
 
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
         }
     }
 
@@ -408,31 +463,25 @@
 
         if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
             mSimState = state;
-            for (int i = 0; i < mSimStateCallbacks.size(); i++) {
-                mSimStateCallbacks.get(i).onSimStateChanged(state);
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                mCallbacks.get(i).onSimStateChanged(state);
             }
         }
     }
 
+    /**
+     * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
+     */
     private void handleClockVisibilityChanged() {
         if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onClockVisibilityChanged();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onClockVisibilityChanged();
         }
     }
 
-    /**
-     * @param pluggedIn state from {@link android.os.BatteryManager#EXTRA_PLUGGED}
-     * @return Whether the device is considered "plugged in."
-     */
-    private static boolean isPluggedIn(BatteryStatus status) {
-        return status.plugged == BatteryManager.BATTERY_PLUGGED_AC
-                || status.plugged == BatteryManager.BATTERY_PLUGGED_USB;
-    }
-
     private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
-        final boolean nowPluggedIn = isPluggedIn(current);
-        final boolean wasPluggedIn = isPluggedIn(old);
+        final boolean nowPluggedIn = current.isPluggedIn();
+        final boolean wasPluggedIn = old.isPluggedIn();
         final boolean stateChangedWhilePluggedIn =
             wasPluggedIn == true && nowPluggedIn == true
             && (old.status != current.status);
@@ -448,16 +497,12 @@
         }
 
         // change where battery needs charging
-        if (!nowPluggedIn && isBatteryLow(current) && current.level != old.level) {
+        if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
             return true;
         }
         return false;
     }
 
-    private static boolean isBatteryLow(BatteryStatus status) {
-        return status.level < LOW_BATTERY_THRESHOLD;
-    }
-
     /**
      * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
      * @return The string to use for the plmn, or null if it should not be shown.
@@ -465,11 +510,7 @@
     private CharSequence getTelephonyPlmnFrom(Intent intent) {
         if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
             final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
-            if (plmn != null) {
-                return plmn;
-            } else {
-                return getDefaultPlmn();
-            }
+            return (plmn != null) ? plmn : getDefaultPlmn();
         }
         return null;
     }
@@ -478,8 +519,7 @@
      * @return The default plmn (no service)
      */
     private CharSequence getDefaultPlmn() {
-        return mContext.getResources().getText(
-                        R.string.lockscreen_carrier_default);
+        return mContext.getResources().getText(R.string.lockscreen_carrier_default);
     }
 
     /**
@@ -497,104 +537,12 @@
     }
 
     /**
-     * Remove the given observer from being registered from any of the kinds
-     * of callbacks.
-     * @param observer The observer to remove (an instance of {@link ConfigurationChangeCallback},
-     *   {@link InfoCallback} or {@link SimStateCallback}
+     * Remove the given observer's callback.
+     *
+     * @param observer The observer to remove
      */
     public void removeCallback(Object observer) {
-        mInfoCallbacks.remove(observer);
-        mSimStateCallbacks.remove(observer);
-    }
-
-    /**
-     * Callback for general information relevant to lock screen.
-     */
-    interface InfoCallback {
-        void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel);
-        void onTimeChanged();
-
-        /**
-         * @param plmn The operator name of the registered network.  May be null if it shouldn't
-         *   be displayed.
-         * @param spn The service provider name.  May be null if it shouldn't be displayed.
-         */
-        void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn);
-
-        /**
-         * Called when the ringer mode changes.
-         * @param state the current ringer state, as defined in
-         * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
-         */
-        void onRingerModeChanged(int state);
-
-        /**
-         * Called when the phone state changes. String will be one of:
-         * {@link TelephonyManager#EXTRA_STATE_IDLE}
-         * {@link TelephonyManager@EXTRA_STATE_RINGING}
-         * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
-         */
-        void onPhoneStateChanged(int phoneState);
-
-        /**
-         * Called when visibility of lockscreen clock changes, such as when
-         * obscured by a widget.
-         */
-        void onClockVisibilityChanged();
-
-        /**
-         * Called when the device becomes provisioned
-         */
-        void onDeviceProvisioned();
-
-        /**
-         * Called when the device policy changes.
-         * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
-         */
-        void onDevicePolicyManagerStateChanged();
-
-        /**
-         * Called when the user changes.
-         */
-        void onUserChanged(int userId);
-    }
-
-    // Simple class that allows methods to easily be overwritten
-    public static class InfoCallbackImpl implements InfoCallback {
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-        }
-
-        public void onTimeChanged() {
-        }
-
-        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-        }
-
-        public void onRingerModeChanged(int state) {
-        }
-
-        public void onPhoneStateChanged(int phoneState) {
-        }
-
-        public void onClockVisibilityChanged() {
-        }
-
-        public void onDeviceProvisioned() {
-        }
-
-        public void onDevicePolicyManagerStateChanged() {
-        }
-
-        public void onUserChanged(int userId) {
-        }
-    }
-
-    /**
-     * Callback to notify of sim state change.
-     */
-    interface SimStateCallback {
-        void onSimStateChanged(IccCardConstants.State simState);
+        mCallbacks.remove(observer);
     }
 
     /**
@@ -602,35 +550,20 @@
      * (see {@link InfoCallback}.
      * @param callback The callback.
      */
-    public void registerInfoCallback(InfoCallback callback) {
-        if (!mInfoCallbacks.contains(callback)) {
-            mInfoCallbacks.add(callback);
+    public void registerCallback(KeyguardUpdateMonitorCallback callback) {
+        if (!mCallbacks.contains(callback)) {
+            mCallbacks.add(callback);
             // Notify listener of the current state
-            callback.onRefreshBatteryInfo(shouldShowBatteryInfo(),isPluggedIn(mBatteryStatus),
-                    mBatteryStatus.level);
+            callback.onRefreshBatteryInfo(mBatteryStatus);
             callback.onTimeChanged();
             callback.onRingerModeChanged(mRingMode);
             callback.onPhoneStateChanged(mPhoneState);
             callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
             callback.onClockVisibilityChanged();
-        } else {
-            if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
-                    new Exception("Whoops"));
-        }
-    }
-
-    /**
-     * Register to be notified of sim state changes.
-     * @param callback The callback.
-     */
-    public void registerSimStateCallback(SimStateCallback callback) {
-        if (!mSimStateCallbacks.contains(callback)) {
-            mSimStateCallbacks.add(callback);
-            // Notify listener of the current state
             callback.onSimStateChanged(mSimState);
         } else {
-            if (DEBUG) Log.e(TAG, "Object tried to add another SIM callback",
-                    new Exception("Whoops"));
+            if (DEBUG) Log.e(TAG, "Object tried to add another callback",
+                    new Exception("Called by"));
         }
     }
 
@@ -655,23 +588,6 @@
         handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
     }
 
-    public boolean isDevicePluggedIn() {
-        return isPluggedIn(mBatteryStatus);
-    }
-
-    public boolean isDeviceCharged() {
-        return mBatteryStatus.status == BATTERY_STATUS_FULL
-                || mBatteryStatus.level >= 100; // in case particular device doesn't flag it
-    }
-
-    public int getBatteryLevel() {
-        return mBatteryStatus.level;
-    }
-
-    public boolean shouldShowBatteryInfo() {
-        return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryStatus);
-    }
-
     public CharSequence getTelephonyPlmn() {
         return mTelephonyPlmn;
     }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitorCallback.java
new file mode 100644
index 0000000..d791419
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitorCallback.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.policy.impl;
+
+import android.app.admin.DevicePolicyManager;
+import android.media.AudioManager;
+
+import com.android.internal.policy.impl.KeyguardUpdateMonitor.BatteryStatus;
+import com.android.internal.telephony.IccCardConstants;
+
+/**
+ * Callback for general information relevant to lock screen.
+ */
+class KeyguardUpdateMonitorCallback {
+    /**
+     * Called when the battery status changes, e.g. when plugged in or unplugged, charge
+     * level, etc. changes.
+     *
+     * @param status current battery status
+     */
+    void onRefreshBatteryInfo(BatteryStatus status) { }
+
+    /**
+     * Called once per minute or when the time changes.
+     */
+    void onTimeChanged() { }
+
+    /**
+     * Called when the carrier PLMN or SPN changes.
+     *
+     * @param plmn The operator name of the registered network.  May be null if it shouldn't
+     *   be displayed.
+     * @param spn The service provider name.  May be null if it shouldn't be displayed.
+     */
+    void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
+
+    /**
+     * Called when the ringer mode changes.
+     * @param state the current ringer state, as defined in
+     * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
+     */
+    void onRingerModeChanged(int state) { }
+
+    /**
+     * Called when the phone state changes. String will be one of:
+     * {@link TelephonyManager#EXTRA_STATE_IDLE}
+     * {@link TelephonyManager@EXTRA_STATE_RINGING}
+     * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
+     */
+    void onPhoneStateChanged(int phoneState) { }
+
+    /**
+     * Called when visibility of lockscreen clock changes, such as when
+     * obscured by a widget.
+     */
+    void onClockVisibilityChanged() { }
+
+    /**
+     * Called when the device becomes provisioned
+     */
+    void onDeviceProvisioned() { }
+
+    /**
+     * Called when the device policy changes.
+     * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
+     */
+    void onDevicePolicyManagerStateChanged() { }
+
+    /**
+     * Called when the user changes.
+     */
+    void onUserSwitched(int userId) { }
+
+    /**
+     * Called when the SIM state changes.
+     * @param simState
+     */
+    void onSimStateChanged(IccCardConstants.State simState) { }
+
+    /**
+     * Called when a user is removed.
+     */
+    void onUserRemoved(int userId) { }
+}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 02eeedf..1fb63db 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -18,7 +18,6 @@
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
 
@@ -90,8 +89,7 @@
  * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
  * thread of the keyguard.
  */
-public class KeyguardViewMediator implements KeyguardViewCallback,
-        KeyguardUpdateMonitor.SimStateCallback {
+public class KeyguardViewMediator implements KeyguardViewCallback {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     private final static boolean DEBUG = false;
     private final static boolean DBG_WAKE = false;
@@ -257,7 +255,38 @@
      */
     private final float mLockSoundVolume;
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onUserSwitched(int userId) {
+            mLockPatternUtils.setCurrentUser(userId);
+            synchronized (KeyguardViewMediator.this) {
+                resetStateLocked();
+            }
+        }
+
+        @Override
+        public void onUserRemoved(int userId) {
+            mLockPatternUtils.removeUser(userId);
+        }
+
+        @Override
+        void onPhoneStateChanged(int phoneState) {
+            synchronized (KeyguardViewMediator.this) {
+                if (TelephonyManager.CALL_STATE_IDLE == phoneState  // call ending
+                        && !mScreenOn                           // screen off
+                        && mExternallyEnabled) {                // not disabled by any app
+
+                    // note: this is a way to gracefully reenable the keyguard when the call
+                    // ends and the screen is off without always reenabling the keyguard
+                    // each time the screen turns off while in call (and having an occasional ugly
+                    // flicker while turning back on the screen and disabling the keyguard again).
+                    if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
+                            + "keyguard is showing");
+                    doKeyguardLocked();
+                }
+            }
+        };
 
         @Override
         public void onClockVisibilityChanged() {
@@ -269,40 +298,86 @@
             mContext.sendBroadcast(mUserPresentIntent);
         }
 
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
+
+            switch (simState) {
+                case NOT_READY:
+                case ABSENT:
+                    // only force lock screen in case of missing sim if user hasn't
+                    // gone through setup wizard
+                    synchronized (this) {
+                        if (!mUpdateMonitor.isDeviceProvisioned()) {
+                            if (!isShowing()) {
+                                if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
+                                        + " we need to show the keyguard since the "
+                                        + "device isn't provisioned yet.");
+                                doKeyguardLocked();
+                            } else {
+                                resetStateLocked();
+                            }
+                        }
+                    }
+                    break;
+                case PIN_REQUIRED:
+                case PUK_REQUIRED:
+                    synchronized (this) {
+                        if (!isShowing()) {
+                            if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
+                                    + "showing; need to show keyguard so user can enter sim pin");
+                            doKeyguardLocked();
+                        } else {
+                            resetStateLocked();
+                        }
+                    }
+                    break;
+                case PERM_DISABLED:
+                    synchronized (this) {
+                        if (!isShowing()) {
+                            if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
+                                  + "keygaurd isn't showing.");
+                            doKeyguardLocked();
+                        } else {
+                            if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+                                  + "show permanently disabled message in lockscreen.");
+                            resetStateLocked();
+                        }
+                    }
+                    break;
+                case READY:
+                    synchronized (this) {
+                        if (isShowing()) {
+                            resetStateLocked();
+                        }
+                    }
+                    break;
+            }
+        }
+
     };
 
     public KeyguardViewMediator(Context context, PhoneWindowManager callback,
             LocalPowerManager powerManager) {
         mContext = context;
-
+        mCallback = callback;
         mRealPowerManager = powerManager;
         mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = mPM.newWakeLock(
-                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
-                "keyguard");
+                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "keyguard");
         mWakeLock.setReferenceCounted(false);
         mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
         mShowKeyguardWakeLock.setReferenceCounted(false);
 
-        mWakeAndHandOff = mPM.newWakeLock(
-                PowerManager.PARTIAL_WAKE_LOCK,
-                "keyguardWakeAndHandOff");
+        mWakeAndHandOff = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "keyguardWakeAndHandOff");
         mWakeAndHandOff.setReferenceCounted(false);
 
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(DELAYED_KEYGUARD_ACTION);
-        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
-        context.registerReceiver(mBroadCastReceiver, filter);
-        mAlarmManager = (AlarmManager) context
-                .getSystemService(Context.ALARM_SERVICE);
-        mCallback = callback;
+        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
+
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 
         mUpdateMonitor = new KeyguardUpdateMonitor(context);
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-
-        mUpdateMonitor.registerSimStateCallback(this);
-
         mLockPatternUtils = new LockPatternUtils(mContext);
         mKeyguardViewProperties
                 = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
@@ -335,11 +410,7 @@
         }
         int lockSoundDefaultAttenuation = context.getResources().getInteger(
                 com.android.internal.R.integer.config_lockSoundVolumeDb);
-        mLockSoundVolume = (float)Math.pow(10, lockSoundDefaultAttenuation/20);
-        IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(Intent.ACTION_USER_SWITCHED);
-        userFilter.addAction(Intent.ACTION_USER_REMOVED);
-        mContext.registerReceiver(mUserChangeReceiver, userFilter);
+        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
     }
 
     /**
@@ -349,6 +420,7 @@
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "onSystemReady");
             mSystemReady = true;
+            mUpdateMonitor.registerCallback(mUpdateCallback);
             doKeyguardLocked();
         }
     }
@@ -726,123 +798,21 @@
         mHandler.sendMessage(msg);
     }
 
-    /** {@inheritDoc} */
-    public void onSimStateChanged(IccCardConstants.State simState) {
-        if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
-
-        switch (simState) {
-            case ABSENT:
-                // only force lock screen in case of missing sim if user hasn't
-                // gone through setup wizard
-                synchronized (this) {
-                    if (!mUpdateMonitor.isDeviceProvisioned()) {
-                        if (!isShowing()) {
-                            if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
-                                    + " we need to show the keyguard since the "
-                                    + "device isn't provisioned yet.");
-                            doKeyguardLocked();
-                        } else {
-                            resetStateLocked();
-                        }
-                    }
-                }
-                break;
-            case PIN_REQUIRED:
-            case PUK_REQUIRED:
-                synchronized (this) {
-                    if (!isShowing()) {
-                        if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, "
-                                + "we need to show keyguard so user can enter their sim pin");
-                        doKeyguardLocked();
-                    } else {
-                        resetStateLocked();
-                    }
-                }
-                break;
-            case PERM_DISABLED:
-                synchronized (this) {
-                    if (!isShowing()) {
-                        if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
-                              + "keygaurd isn't showing.");
-                        doKeyguardLocked();
-                    } else {
-                        if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
-                              + "show permanently disabled message in lockscreen.");
-                        resetStateLocked();
-                    }
-                }
-                break;
-            case READY:
-                synchronized (this) {
-                    if (isShowing()) {
-                        resetStateLocked();
-                    }
-                }
-                break;
-        }
-    }
-
     public boolean isSecure() {
         return mKeyguardViewProperties.isSecure();
     }
 
-    private void onUserSwitched(int userId) {
-        mLockPatternUtils.setCurrentUser(userId);
-        synchronized (KeyguardViewMediator.this) {
-            resetStateLocked();
-        }
-    }
-
-    private void onUserRemoved(int userId) {
-        mLockPatternUtils.removeUser(userId);
-    }
-
-    private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                onUserSwitched(intent.getIntExtra(Intent.EXTRA_USERID, 0));
-            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, 0));
-            }
-        }
-    };
-
-    private BroadcastReceiver mBroadCastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (action.equals(DELAYED_KEYGUARD_ACTION)) {
-
-                int sequence = intent.getIntExtra("seq", 0);
-
+            if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
+                final int sequence = intent.getIntExtra("seq", 0);
                 if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
                         + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
-
                 synchronized (KeyguardViewMediator.this) {
                     if (mDelayedShowingSequence == sequence) {
-                        // Don't play lockscreen SFX if the screen went off due to
-                        // timeout.
+                        // Don't play lockscreen SFX if the screen went off due to timeout.
                         mSuppressNextLockSound = true;
-
-                        doKeyguardLocked();
-                    }
-                }
-            } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
-                mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
-
-                synchronized (KeyguardViewMediator.this) {
-                    if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)  // call ending
-                            && !mScreenOn                           // screen off
-                            && mExternallyEnabled) {                // not disabled by any app
-
-                        // note: this is a way to gracefully reenable the keyguard when the call
-                        // ends and the screen is off without always reenabling the keyguard
-                        // each time the screen turns off while in call (and having an occasional ugly
-                        // flicker while turning back on the screen and disabling the keyguard again).
-                        if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
-                                + "keyguard is showing");
                         doKeyguardLocked();
                     }
                 }
@@ -850,7 +820,6 @@
         }
     };
 
-
     /**
      * When a key is received when the screen is off and the keyguard is showing,
      * we need to decide whether to actually turn on the screen, and if so, tell
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 041211c..32aec10 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -17,13 +17,10 @@
 package com.android.internal.policy.impl;
 
 import com.android.internal.R;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
+import com.android.internal.policy.impl.KeyguardUpdateMonitor.BatteryStatus;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockScreenWidgetCallback;
-import com.android.internal.widget.LockScreenWidgetInterface;
 import com.android.internal.widget.TransportControlView;
 
 import android.accounts.Account;
@@ -40,10 +37,8 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcelable;
@@ -449,9 +444,8 @@
         mWindowController = controller;
         mSuppressBiometricUnlock = sIsFirstAppearanceAfterBoot;
         sIsFirstAppearanceAfterBoot = false;
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
         mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         /**
          * We'll get key events the current screen doesn't use. see
@@ -692,17 +686,17 @@
         post(mRecreateRunnable);
     }
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
+        public void onRefreshBatteryInfo(BatteryStatus status) {
             // When someone plugs in or unplugs the device, we hide the biometric sensor area and
             // suppress its startup for the next onScreenTurnedOn().  Since plugging/unplugging
             // causes the screen to turn on, the biometric unlock would start if it wasn't
             // suppressed.
             //
             // However, if the biometric unlock is already running, we do not want to interrupt it.
+            final boolean pluggedIn = status.isPluggedIn();
             if (mBiometricUnlock != null && mPluggedIn != pluggedIn
                     && !mBiometricUnlock.isRunning()) {
                 mBiometricUnlock.stop();
@@ -732,7 +726,7 @@
         }
 
         @Override
-        public void onUserChanged(int userId) {
+        public void onUserSwitched(int userId) {
             if (mBiometricUnlock != null) {
                 mBiometricUnlock.stop();
             }
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
index 6d3c20a6..5066e3c 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
@@ -58,7 +58,6 @@
         final IccCardConstants.State simState = mUpdateMonitor.getSimState();
         return (simState == IccCardConstants.State.PIN_REQUIRED
                 || simState == IccCardConstants.State.PUK_REQUIRED
-                || simState == IccCardConstants.State.ABSENT
                 || simState == IccCardConstants.State.PERM_DISABLED);
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 26078ec..82181d3 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -17,8 +17,6 @@
 package com.android.internal.policy.impl;
 
 import com.android.internal.R;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.SlidingTab;
@@ -86,7 +84,7 @@
     // Is there a vibrator
     private final boolean mHasVibrator;
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
         public void onRingerModeChanged(int state) {
@@ -102,9 +100,7 @@
             updateTargets();
         }
 
-    };
-
-    SimStateCallback mSimStateCallback = new SimStateCallback() {
+        @Override
         public void onSimStateChanged(IccCardConstants.State simState) {
             updateTargets();
         }
@@ -582,7 +578,6 @@
     /** {@inheritDoc} */
     public void onPause() {
         mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
         mStatusViewManager.onPause();
         mUnlockWidgetMethods.reset(false);
     }
@@ -597,8 +592,7 @@
     public void onResume() {
         // We don't want to show the camera target if SIM state prevents us from
         // launching the camera. So watch for SIM changes...
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         mStatusViewManager.onResume();
         postDelayed(mOnResumePing, ON_RESUME_PING_DELAY);
@@ -607,7 +601,6 @@
     /** {@inheritDoc} */
     public void cleanUp() {
         mUpdateMonitor.removeCallback(mInfoCallback); // this must be first
-        mUpdateMonitor.removeCallback(mSimStateCallback);
         mUnlockWidgetMethods.cleanUp();
         mLockPatternUtils = null;
         mUpdateMonitor = null;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 0aa3018..3e96f9bc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -613,8 +613,7 @@
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 width, WRAP_CONTENT,
                 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
-                WindowManager.LayoutParams.FLAG_DITHER
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 st.decorView.mDefaultOpacity);
 
@@ -2841,6 +2840,8 @@
             mDecor = generateDecor();
             mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
             mDecor.setIsRootNamespace(true);
+            mDecor.setLayoutDirection(
+                    getContext().getResources().getConfiguration().layoutDirection);
         }
         if (mContentParent == null) {
             mContentParent = generateLayout(mDecor);
@@ -2850,6 +2851,7 @@
 
             mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
             if (mTitleView != null) {
+                mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
                 if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                     View titleContainer = findViewById(com.android.internal.R.id.title_container);
                     if (titleContainer != null) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 25da642..cca9cbb 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -125,6 +125,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
@@ -182,6 +183,7 @@
     static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
 
     // wallpaper is at the bottom, though the window manager may move it.
+    static final int UNIVERSE_BACKGROUND_LAYER = 1;
     static final int WALLPAPER_LAYER = 2;
     static final int APPLICATION_LAYER = 2;
     static final int PHONE_LAYER = 3;
@@ -1030,13 +1032,9 @@
             mHasSystemNavBar = false;
             mNavigationBarCanMove = true;
         } else if (shortSizeDp < 720) {
-            // 600-719dp: "phone" UI with modifications for larger screens
+            // 600+dp: "phone" UI with modifications for larger screens
             mHasSystemNavBar = false;
             mNavigationBarCanMove = false;
-        } else {
-            // 720dp: "tablet" UI with a single combined status & navigation bar
-            mHasSystemNavBar = true;
-            mNavigationBarCanMove = false;
         }
 
         if (!mHasSystemNavBar) {
@@ -1374,6 +1372,8 @@
             return HIDDEN_NAV_CONSUMER_LAYER;
         case TYPE_DREAM:
             return SCREENSAVER_LAYER;
+        case TYPE_UNIVERSE_BACKGROUND:
+            return UNIVERSE_BACKGROUND_LAYER;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return APPLICATION_LAYER;
@@ -1400,6 +1400,10 @@
         return STATUS_BAR_LAYER;
     }
 
+    public int getAboveUniverseLayer() {
+        return SYSTEM_ERROR_LAYER;
+    }
+
     public boolean hasSystemNavBar() {
         return mHasSystemNavBar;
     }
@@ -1453,7 +1457,8 @@
     public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
         return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
                 && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
-                && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
+                && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER
+                && attrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
     }
 
     /** {@inheritDoc} */
@@ -2370,16 +2375,6 @@
             if (mNavigationBarOnBottom) {
                 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
                 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
-                if (mHdmiPlugged) {
-                    // Move the nav bar up if the external display is the same aspect ratio
-                    // but shorter.  This avoids clipping on the external display.
-                    boolean sameAspect = mExternalDisplayHeight > 0 && displayHeight > 0
-                        && ((float) mExternalDisplayWidth / mExternalDisplayHeight > 1)
-                        == ((float) displayWidth / displayHeight > 1);
-                    if (sameAspect && top > mExternalDisplayHeight) {
-                        top = mExternalDisplayHeight;
-                    }
-                }
                 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
                 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
                 if (navVisible) {
@@ -2399,11 +2394,6 @@
             } else {
                 // Landscape screen; nav bar goes to the right.
                 int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
-                if (mHdmiPlugged) {
-                    if (left > mExternalDisplayWidth) {
-                        left = mExternalDisplayWidth;
-                    }
-                }
                 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
                 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
                 if (navVisible) {
@@ -2720,7 +2710,8 @@
                     pf.top = df.top = mUnrestrictedScreenTop;
                     pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                     pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
-                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
+                } else if (attrs.type == TYPE_BOOT_PROGRESS
+                        || attrs.type == TYPE_UNIVERSE_BACKGROUND) {
                     // Boot progress screen always covers entire display.
                     pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
                     pf.top = df.top = cf.top = mUnrestrictedScreenTop;
diff --git a/services/common_time/Android.mk b/services/common_time/Android.mk
index e534d49..0606ab4 100644
--- a/services/common_time/Android.mk
+++ b/services/common_time/Android.mk
@@ -14,7 +14,8 @@
     common_time_server_packets.cpp \
     clock_recovery.cpp \
     common_clock.cpp \
-    main.cpp
+    main.cpp \
+    utils.cpp
 
 # Uncomment to enable vesbose logging and debug service.
 #TIME_SERVICE_DEBUG=true
diff --git a/services/common_time/clock_recovery.cpp b/services/common_time/clock_recovery.cpp
index 6c98d32..3a7c70c 100644
--- a/services/common_time/clock_recovery.cpp
+++ b/services/common_time/clock_recovery.cpp
@@ -53,6 +53,21 @@
 
     local_clock_can_slew_ = local_clock_->initCheck() &&
                            (local_clock_->setLocalSlew(0) == OK);
+    tgt_correction_ = 0;
+    cur_correction_ = 0;
+
+    // Precompute the max rate at which we are allowed to change the VCXO
+    // control.
+    uint64_t N = 0x10000ull * 1000ull;
+    uint64_t D = local_clock_->getLocalFreq() * kMinFullRangeSlewChange_mSec;
+    LinearTransform::reduce(&N, &D);
+    while ((N > INT32_MAX) || (D > UINT32_MAX)) {
+        N >>= 1;
+        D >>= 1;
+        LinearTransform::reduce(&N, &D);
+    }
+    time_to_cur_slew_.a_to_b_numer = static_cast<int32_t>(N);
+    time_to_cur_slew_.a_to_b_denom = static_cast<uint32_t>(D);
 
     reset(true, true);
 
@@ -85,6 +100,9 @@
 const int64_t ClockRecoveryLoop::control_thresh_ = 10000;
 const float ClockRecoveryLoop::COmin = -100.0f;
 const float ClockRecoveryLoop::COmax = 100.0f;
+const uint32_t ClockRecoveryLoop::kMinFullRangeSlewChange_mSec = 300;
+const int ClockRecoveryLoop::kSlewChangeStepPeriod_mSec = 10;
+
 
 void ClockRecoveryLoop::reset(bool position, bool frequency) {
     Mutex::Autolock lock(&lock_);
@@ -144,7 +162,7 @@
     int64_t observed_common;
     int64_t delta;
     float delta_f, dCO;
-    int32_t correction_cur;
+    int32_t tgt_correction;
 
     if (OK != common_clock_->localToCommon(local_time, &observed_common)) {
         // Since we just checked to make certain that this conversion was valid,
@@ -207,6 +225,9 @@
     if (current_point == min_rtt || rtt < control_thresh_) {
         delta_f = delta = nominal_common_time - observed_common;
 
+        last_error_est_valid_ = true;
+        last_error_est_usec_ = delta;
+
         // Compute the error then clamp to the panic threshold.  If we ever
         // exceed this amt of error, its time to panic and reset the system.
         // Given that the error in the measurement of the error could be as
@@ -240,7 +261,6 @@
 
     // Save error terms for later.
     last_delta_f_ = delta_f;
-    last_delta_ = delta;
 
     // Clamp CO to +/- 100ppm.
     if (CO < COmin)
@@ -254,23 +274,20 @@
 
     // Convert PPM to 16-bit int range. Add some guard band (-0.01) so we
     // don't get fp weirdness.
-    correction_cur = CO * 327.66;
+    tgt_correction = CO * 327.66;
 
     // If there was a change in the amt of correction to use, update the
     // system.
-    if (correction_cur_ != correction_cur) {
-        correction_cur_ = correction_cur;
-        applySlew();
-    }
+    setTargetCorrection_l(tgt_correction);
 
-    LOG_TS("clock_loop %lld %f %f %f %d\n", raw_delta, delta_f, CO, CObias, correction_cur);
+    LOG_TS("clock_loop %lld %f %f %f %d\n", raw_delta, delta_f, CO, CObias, tgt_correction);
 
 #ifdef TIME_SERVICE_DEBUG
     diag_thread_->pushDisciplineEvent(
             local_time,
             observed_common,
             nominal_common_time,
-            correction_cur,
+            tgt_correction,
             rtt);
 #endif
 
@@ -280,8 +297,8 @@
 int32_t ClockRecoveryLoop::getLastErrorEstimate() {
     Mutex::Autolock lock(&lock_);
 
-    if (last_delta_valid_)
-        return last_delta_;
+    if (last_error_est_valid_)
+        return last_error_est_usec_;
     else
         return ICommonClock::kErrorEstimateUnknown;
 }
@@ -295,27 +312,112 @@
     }
 
     if (frequency) {
-        last_delta_valid_ = false;
-        last_delta_ = 0;
+        last_error_est_valid_ = false;
+        last_error_est_usec_ = 0;
         last_delta_f_ = 0.0;
-        correction_cur_ = 0x0;
         CO = 0.0f;
         lastCObias = CObias = 0.0f;
-        applySlew();
+        setTargetCorrection_l(0);
+        applySlew_l();
     }
 
     filter_wr_   = 0;
     filter_full_ = false;
 }
 
-void ClockRecoveryLoop::applySlew() {
+void ClockRecoveryLoop::setTargetCorrection_l(int32_t tgt) {
+    // When we make a change to the slew rate, we need to be careful to not
+    // change it too quickly as it can anger some HDMI sinks out there, notably
+    // some Sony panels from the 2010-2011 timeframe.  From experimenting with
+    // some of these sinks, it seems like swinging from one end of the range to
+    // another in less that 190mSec or so can start to cause trouble.  Adding in
+    // a hefty margin, we limit the system to a full range sweep in no less than
+    // 300mSec.
+    if (tgt_correction_ != tgt) {
+        int64_t now = local_clock_->getLocalTime();
+        status_t res;
+
+        tgt_correction_ = tgt;
+
+        // Set up the transformation to figure out what the slew should be at
+        // any given point in time in the future.
+        time_to_cur_slew_.a_zero = now;
+        time_to_cur_slew_.b_zero = cur_correction_;
+
+        // Make sure the sign of the slope is headed in the proper direction.
+        bool needs_increase = (cur_correction_ < tgt_correction_);
+        bool is_increasing  = (time_to_cur_slew_.a_to_b_numer > 0);
+        if (( needs_increase && !is_increasing) ||
+            (!needs_increase &&  is_increasing)) {
+            time_to_cur_slew_.a_to_b_numer = -time_to_cur_slew_.a_to_b_numer;
+        }
+
+        // Finally, figure out when the change will be finished and start the
+        // slew operation.
+        time_to_cur_slew_.doReverseTransform(tgt_correction_,
+                                             &slew_change_end_time_);
+
+        applySlew_l();
+    }
+}
+
+bool ClockRecoveryLoop::applySlew_l() {
+    bool ret = true;
+
+    // If cur == tgt, there is no ongoing sleq rate change and we are already
+    // finished.
+    if (cur_correction_ == tgt_correction_)
+        goto bailout;
+
     if (local_clock_can_slew_) {
-        local_clock_->setLocalSlew(correction_cur_);
+        int64_t now = local_clock_->getLocalTime();
+        int64_t tmp;
+
+        if (now >= slew_change_end_time_) {
+            cur_correction_ = tgt_correction_;
+            next_slew_change_timeout_.setTimeout(-1);
+        } else {
+            time_to_cur_slew_.doForwardTransform(now, &tmp);
+
+            if (tmp > INT16_MAX)
+                cur_correction_ = INT16_MAX;
+            else if (tmp < INT16_MIN)
+                cur_correction_ = INT16_MIN;
+            else
+                cur_correction_ = static_cast<int16_t>(tmp);
+
+            next_slew_change_timeout_.setTimeout(kSlewChangeStepPeriod_mSec);
+            ret = false;
+        }
+
+        local_clock_->setLocalSlew(cur_correction_);
     } else {
+        // Since we are not actually changing the rate of a HW clock, we don't
+        // need to worry to much about changing the slew rate so fast that we
+        // anger any downstream HDMI devices.
+        cur_correction_ = tgt_correction_;
+        next_slew_change_timeout_.setTimeout(-1);
+
         // The SW clock recovery implemented by the common clock class expects
         // values expressed in PPM. CO is in ppm.
         common_clock_->setSlew(local_clock_->getLocalTime(), CO);
     }
+
+bailout:
+    return ret;
+}
+
+int ClockRecoveryLoop::applyRateLimitedSlew() {
+    Mutex::Autolock lock(&lock_);
+
+    int ret = next_slew_change_timeout_.msecTillTimeout();
+    if (!ret) {
+        if (applySlew_l())
+            next_slew_change_timeout_.setTimeout(-1);
+        ret = next_slew_change_timeout_.msecTillTimeout();
+    }
+
+    return ret;
 }
 
 }  // namespace android
diff --git a/services/common_time/clock_recovery.h b/services/common_time/clock_recovery.h
index b7362be..b6c87ff 100644
--- a/services/common_time/clock_recovery.h
+++ b/services/common_time/clock_recovery.h
@@ -26,6 +26,8 @@
 #include "diag_thread.h"
 #endif
 
+#include "utils.h"
+
 namespace android {
 
 class CommonClock;
@@ -42,6 +44,11 @@
                              int64_t data_point_rtt);
     int32_t getLastErrorEstimate();
 
+    // Applies the next step in any ongoing slew change operation.  Returns a
+    // timeout suitable for use with poll/select indicating the number of mSec
+    // until the next change should be applied.
+    int applyRateLimitedSlew();
+
   private:
 
     // Tuned using the "Good Gain" method.
@@ -87,7 +94,8 @@
     static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count);
 
     void reset_l(bool position, bool frequency);
-    void applySlew();
+    void setTargetCorrection_l(int32_t tgt);
+    bool applySlew_l();
 
     // The local clock HW abstraction we use as the basis for common time.
     LocalClock* local_clock_;
@@ -100,11 +108,15 @@
 
     // parameters maintained while running and reset during a reset
     // of the frequency correction.
-    bool    last_delta_valid_;
-    int32_t last_delta_;
+    bool    last_error_est_valid_;
+    int32_t last_error_est_usec_;
     float last_delta_f_;
     int32_t integrated_error_;
-    int32_t correction_cur_;
+    int32_t tgt_correction_;
+    int32_t cur_correction_;
+    LinearTransform time_to_cur_slew_;
+    int64_t slew_change_end_time_;
+    Timeout next_slew_change_timeout_;
 
     // Contoller Output.
     float CO;
@@ -128,6 +140,15 @@
     DisciplineDataPoint startup_filter_data_[kStartupFilterSize];
     uint32_t startup_filter_wr_;
 
+    // Minimum number of milliseconds over which we allow a full range change
+    // (from rail to rail) of the VCXO control signal.  This is the rate
+    // limiting factor which keeps us from changing the clock rate so fast that
+    // we get in trouble with certain HDMI sinks.
+    static const uint32_t kMinFullRangeSlewChange_mSec;
+
+    // How much time (in msec) to wait 
+    static const int kSlewChangeStepPeriod_mSec;
+
 #ifdef TIME_SERVICE_DEBUG
     sp<DiagThread> diag_thread_;
 #endif
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index 7a4986b..16be8f1 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -107,6 +107,9 @@
     , mTimelineID(ICommonClock::kInvalidTimelineID)
     , mClockSynced(false)
     , mCommonClockHasClients(false)
+    , mStateChangeLog("Recent State Change Events", 30)
+    , mElectionLog("Recent Master Election Traffic", 30)
+    , mBadPktLog("Recent Bad Packet RX Info", 8)
     , mInitial_WhoIsMasterRequestTimeouts(0)
     , mClient_MasterDeviceID(0)
     , mClient_MasterDevicePriority(0)
@@ -202,9 +205,11 @@
     // run the state machine
     while (!exitPending()) {
         struct pollfd pfds[2];
-        int rc;
+        int rc, timeout;
         int eventCnt = 0;
         int64_t wakeupTime;
+        uint32_t t1, t2;
+        bool needHandleTimeout = false;
 
         // We are always interested in our wakeup FD.
         pfds[eventCnt].fd      = mWakeupThreadFD;
@@ -221,10 +226,14 @@
             eventCnt++;
         }
 
+        t1 = static_cast<uint32_t>(mCurTimeout.msecTillTimeout());
+        t2 = static_cast<uint32_t>(mClockRecovery.applyRateLimitedSlew());
+        timeout = static_cast<int>(t1 < t2 ? t1 : t2);
+
         // Note, we were holding mLock when this function was called.  We
         // release it only while we are blocking and hold it at all other times.
         mLock.unlock();
-        rc          = poll(pfds, eventCnt, mCurTimeout.msecTillTimeout());
+        rc          = poll(pfds, eventCnt, timeout);
         wakeupTime  = mLocalClock.getLocalTime();
         mLock.lock();
 
@@ -238,8 +247,11 @@
             return false;
         }
 
-        if (rc == 0)
-            mCurTimeout.setTimeout(kInfiniteTimeout);
+        if (rc == 0) {
+            needHandleTimeout = !mCurTimeout.msecTillTimeout();
+            if (needHandleTimeout)
+                mCurTimeout.setTimeout(kInfiniteTimeout);
+        }
 
         // Were we woken up on purpose?  If so, clear the eventfd with a read.
         if (pfds[0].revents)
@@ -321,10 +333,11 @@
             // we are in any other state (CLIENT, RONIN or WAIT_FOR_ELECTION),
             // then transition to either INITIAL or MASTER depending on whether
             // or not our timeline is valid.
-            ALOGI("Entering networkless mode interface is %s, "
-                 "shouldAutoDisable = %s",
-                 mBindIfaceValid ? "valid" : "invalid",
-                 shouldAutoDisable() ? "true" : "false");
+            mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+                    "Entering networkless mode interface is %s, "
+                    "shouldAutoDisable = %s",
+                    mBindIfaceValid ? "valid" : "invalid",
+                    shouldAutoDisable() ? "true" : "false");
             if ((mState != ICommonClock::STATE_INITIAL) &&
                 (mState != ICommonClock::STATE_MASTER)) {
                 if (mTimelineID == ICommonClock::kInvalidTimelineID)
@@ -336,9 +349,8 @@
             continue;
         }
 
-        // Did we wakeup with no signalled events across all of our FDs?  If so,
-        // we must have hit our timeout.
-        if (rc == 0) {
+        // Time to handle the timeouts?
+        if (needHandleTimeout) {
             if (!handleTimeout())
                 ALOGE("handleTimeout failed");
             continue;
@@ -407,20 +419,23 @@
 
     sockaddrToString(mMasterElectionEP, true, masterElectionEPStr,
                      sizeof(masterElectionEPStr));
-    ALOGI("Building socket :: bind = %s master election = %s",
-         mBindIface.string(), masterElectionEPStr);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+                        "Building socket :: bind = %s master election = %s",
+                        mBindIface.string(), masterElectionEPStr);
 
     // TODO: add proper support for IPv6.  Right now, we block IPv6 addresses at
     // the configuration interface level.
     if (AF_INET != mMasterElectionEP.ss_family) {
-        ALOGW("TODO: add proper IPv6 support");
+        mStateChangeLog.log(ANDROID_LOG_WARN, LOG_TAG,
+                            "TODO: add proper IPv6 support");
         goto bailout;
     }
 
     // open a UDP socket for the timeline serivce
     mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     if (mSocket < 0) {
-        ALOGE("Failed to create socket (errno = %d)", errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to create socket (errno = %d)", errno);
         goto bailout;
     }
 
@@ -432,8 +447,9 @@
     rc = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE,
                     (void *)&ifr, sizeof(ifr));
     if (rc) {
-        ALOGE("Failed to bind socket at to interface %s (errno = %d)",
-              ifr.ifr_name, errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to bind socket at to interface %s "
+                            "(errno = %d)", ifr.ifr_name, errno);
         goto bailout;
     }
 
@@ -451,8 +467,9 @@
               reinterpret_cast<const sockaddr *>(&bindAddr),
               sizeof(bindAddr));
     if (rc) {
-        ALOGE("Failed to bind socket to port %hu (errno = %d)",
-              ntohs(bindAddr.sin_port), errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to bind socket to port %hu (errno = %d)",
+                            ntohs(bindAddr.sin_port), errno);
         goto bailout;
     }
 
@@ -475,11 +492,23 @@
         rc = setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
                         &zero, sizeof(zero));
         if (rc == -1) {
-            ALOGE("Failed to disable multicast loopback (errno = %d)", errno);
+            mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                                "Failed to disable multicast loopback "
+                                "(errno = %d)", errno);
             goto bailout;
         }
     } else
-    if (ntohl(ipv4_addr->sin_addr.s_addr) != 0xFFFFFFFF) {
+    if (ntohl(ipv4_addr->sin_addr.s_addr) == 0xFFFFFFFF) {
+        // If the master election address is the broadcast address, then enable
+        // the broadcast socket option
+        rc = setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
+        if (rc == -1) {
+            mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                                "Failed to enable broadcast (errno = %d)",
+                                errno);
+            goto bailout;
+        }
+    } else {
         // If the master election address is neither broadcast, nor multicast,
         // then we are misconfigured.  The config API layer should prevent this
         // from ever happening.
@@ -490,7 +519,8 @@
     // the local subnet)
     rc = setsockopt(mSocket, IPPROTO_IP, IP_TTL, &one, sizeof(one));
     if (rc == -1) {
-        ALOGE("Failed to set TTL to %d (errno = %d)", one, errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to set TTL to %d (errno = %d)", one, errno);
         goto bailout;
     }
 
@@ -552,6 +582,31 @@
            ((devicePrio1 == devicePrio2) && (deviceID1 > deviceID2)));
 }
 
+static void hexDumpToString(const uint8_t* src, size_t src_len,
+                            char* dst, size_t dst_len) {
+    size_t offset;
+    size_t i;
+
+    for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
+        int res;
+        if (0 == (i % 16)) {
+            res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+            if (res < 0)
+                break;
+            offset += res;
+            if (offset >= dst_len)
+                break;
+        }
+
+        res = snprintf(dst + offset, dst_len - offset, " %02x", src[i]);
+        if (res < 0)
+            break;
+        offset += res;
+    }
+
+    dst[dst_len - 1] = 0;
+}
+
 bool CommonTimeServer::handlePacket() {
     uint8_t buf[256];
     struct sockaddr_storage srcAddr;
@@ -562,14 +617,24 @@
             reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen);
 
     if (recvBytes < 0) {
-        ALOGE("%s:%d recvfrom failed", __PRETTY_FUNCTION__, __LINE__);
+        mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                       "recvfrom failed (res %d, errno %d)",
+                       recvBytes, errno);
         return false;
     }
 
     UniversalTimeServicePacket pkt;
-    recvBytes = pkt.deserializePacket(buf, recvBytes, mSyncGroupID);
-    if (recvBytes < 0)
+    if (pkt.deserializePacket(buf, recvBytes, mSyncGroupID) < 0) {
+        char hex[256];
+        char srcEPStr[64];
+
+        hexDumpToString(buf, static_cast<size_t>(recvBytes), hex, sizeof(hex));
+        sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+
+        mBadPktLog.log("Failed to parse %d byte packet from %s.%s",
+                       recvBytes, srcEPStr, hex);
         return false;
+    }
 
     bool result;
     switch (pkt.packetType) {
@@ -597,8 +662,13 @@
             break;
 
         default: {
-            ALOGD("%s:%d unknown packet type(%d)",
-                    __PRETTY_FUNCTION__, __LINE__, pkt.packetType);
+            char srcEPStr[64];
+            sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+
+            mBadPktLog.log(ANDROID_LOG_WARN, LOG_TAG,
+                           "unknown packet type (%d) from %s",
+                           pkt.packetType, srcEPStr);
+
             result = false;
         } break;
     }
@@ -682,6 +752,14 @@
 bool CommonTimeServer::handleWhoIsMasterRequest(
         const WhoIsMasterRequestPacket* request,
         const sockaddr_storage& srcAddr) {
+
+    char srcEPStr[64];
+    sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+    mElectionLog.log("RXed WhoIs master request while in state %s.  "
+                     "src %s reqTID %016llx ourTID %016llx",
+                     stateToString(mState), srcEPStr,
+                     request->timelineID, mTimelineID);
+
     if (mState == ICommonClock::STATE_MASTER) {
         // is this request related to this master's timeline?
         if (request->timelineID != ICommonClock::kInvalidTimelineID &&
@@ -693,6 +771,13 @@
         pkt.deviceID = mDeviceID;
         pkt.devicePriority = effectivePriority();
 
+        mElectionLog.log("TXing WhoIs master resp to %s while in state %s.  "
+                         "ourTID %016llx ourGID %016llx ourDID %016llx "
+                         "ourPrio %u",
+                         srcEPStr, stateToString(mState),
+                         mTimelineID, mSyncGroupID,
+                         pkt.deviceID, pkt.devicePriority);
+
         uint8_t buf[256];
         ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
         if (bufSz < 0)
@@ -744,6 +829,17 @@
 bool CommonTimeServer::handleWhoIsMasterResponse(
         const WhoIsMasterResponsePacket* response,
         const sockaddr_storage& srcAddr) {
+    char srcEPStr[64];
+    sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+    mElectionLog.log("RXed WhoIs master response while in state %s.  "
+                     "src %s respTID %016llx respDID %016llx respPrio %u "
+                     "ourTID %016llx",
+                     stateToString(mState), srcEPStr,
+                     response->timelineID,
+                     response->deviceID,
+                     static_cast<uint32_t>(response->devicePriority),
+                     mTimelineID);
+
     if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN) {
         return becomeClient(srcAddr,
                             response->deviceID,
@@ -900,6 +996,14 @@
     uint8_t  newDevicePrio = packet->devicePriority;
     uint64_t newTimelineID = packet->timelineID;
 
+    char srcEPStr[64];
+    sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+    mElectionLog.log("RXed master announcement while in state %s.  "
+                     "src %s srcDevID %lld srcPrio %u srcTID %016llx",
+                     stateToString(mState), srcEPStr,
+                     newDeviceID, static_cast<uint32_t>(newDevicePrio),
+                     newTimelineID);
+
     if (mState == ICommonClock::STATE_INITIAL ||
         mState == ICommonClock::STATE_RONIN ||
         mState == ICommonClock::STATE_WAIT_FOR_ELECTION) {
@@ -956,6 +1060,15 @@
     uint8_t buf[256];
     ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
     if (bufSz >= 0) {
+        char dstEPStr[64];
+        sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
+        mElectionLog.log("TXing WhoIs master request to %s while in state %s.  "
+                         "ourTID %016llx ourGID %016llx ourDID %016llx "
+                         "ourPrio %u",
+                         dstEPStr, stateToString(mState),
+                         mTimelineID, mSyncGroupID,
+                         pkt.senderDeviceID, pkt.senderDevicePriority);
+
         ssize_t sendBytes = sendto(
                 mSocket, buf, bufSz, 0,
                 reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
@@ -1032,6 +1145,15 @@
     uint8_t buf[256];
     ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
     if (bufSz >= 0) {
+        char dstEPStr[64];
+        sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
+        mElectionLog.log("TXing Master announcement to %s while in state %s.  "
+                         "ourTID %016llx ourGID %016llx ourDID %016llx "
+                         "ourPrio %u",
+                         dstEPStr, stateToString(mState),
+                         mTimelineID, mSyncGroupID,
+                         pkt.deviceID, pkt.devicePriority);
+
         ssize_t sendBytes = sendto(
                 mSocket, buf, bufSz, 0,
                 reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
@@ -1054,15 +1176,16 @@
     sockaddrToString(masterEP, true, newEPStr, sizeof(newEPStr));
     sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr));
 
-    ALOGI("%s --> CLIENT (%s) :%s"
-         " OldMaster: %02x-%014llx::%016llx::%s"
-         " NewMaster: %02x-%014llx::%016llx::%s",
-         stateToString(mState), cause,
-         (mTimelineID != timelineID) ? " (new timeline)" : "",
-         mClient_MasterDevicePriority, mClient_MasterDeviceID,
-         mTimelineID, oldEPStr,
-         masterDevicePriority, masterDeviceID,
-         timelineID, newEPStr);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+            "%s --> CLIENT (%s) :%s"
+            " OldMaster: %02x-%014llx::%016llx::%s"
+            " NewMaster: %02x-%014llx::%016llx::%s",
+            stateToString(mState), cause,
+            (mTimelineID != timelineID) ? " (new timeline)" : "",
+            mClient_MasterDevicePriority, mClient_MasterDeviceID,
+            mTimelineID, oldEPStr,
+            masterDevicePriority, masterDeviceID,
+            timelineID, newEPStr);
 
     if (mTimelineID != timelineID) {
         // start following a new timeline
@@ -1115,11 +1238,12 @@
         notifyClockSync();
     }
 
-    ALOGI("%s --> MASTER (%s) : %s timeline %016llx",
-         stateToString(mState), cause,
-         (oldTimelineID == mTimelineID) ? "taking ownership of"
-                                        : "creating new",
-         mTimelineID);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+            "%s --> MASTER (%s) : %s timeline %016llx",
+            stateToString(mState), cause,
+            (oldTimelineID == mTimelineID) ? "taking ownership of"
+                                           : "creating new",
+            mTimelineID);
 
     memset(&mMasterEP, 0, sizeof(mMasterEP));
     mMasterEPValid = false;
@@ -1148,7 +1272,8 @@
     mMasterEPValid = false;
 
     if (mCommonClock.isValid()) {
-        ALOGI("%s --> RONIN (%s) : lost track of previously valid timeline "
+        mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+             "%s --> RONIN (%s) : lost track of previously valid timeline "
              "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
              stateToString(mState), cause,
              mClient_MasterDevicePriority, mClient_MasterDeviceID,
@@ -1161,7 +1286,8 @@
         setState(ICommonClock::STATE_RONIN);
         return sendWhoIsMasterRequest();
     } else {
-        ALOGI("%s --> INITIAL (%s) : never synced timeline "
+        mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+             "%s --> INITIAL (%s) : never synced timeline "
              "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
              stateToString(mState), cause,
              mClient_MasterDevicePriority, mClient_MasterDeviceID,
@@ -1175,7 +1301,8 @@
 }
 
 bool CommonTimeServer::becomeWaitForElection(const char* cause) {
-    ALOGI("%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+         "%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
          " waiting %d mSec for completion.",
          stateToString(mState), cause, kWaitForElection_TimeoutMs);
 
@@ -1185,7 +1312,9 @@
 }
 
 bool CommonTimeServer::becomeInitial(const char* cause) {
-    ALOGI("Entering INITIAL (%s), total reset.", cause);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+                        "Entering INITIAL (%s), total reset.",
+                        cause);
 
     setState(ICommonClock::STATE_INITIAL);
 
@@ -1326,29 +1455,6 @@
     }
 }
 
-void CommonTimeServer::TimeoutHelper::setTimeout(int msec) {
-    mTimeoutValid = (msec >= 0);
-    if (mTimeoutValid)
-        mEndTime = systemTime() +
-                   (static_cast<nsecs_t>(msec) * 1000000);
-}
-
-int CommonTimeServer::TimeoutHelper::msecTillTimeout() {
-    if (!mTimeoutValid)
-        return kInfiniteTimeout;
-
-    nsecs_t now = systemTime();
-    if (now >= mEndTime)
-        return 0;
-
-    uint64_t deltaMsec = (((mEndTime - now) + 999999) / 1000000);
-
-    if (deltaMsec > static_cast<uint64_t>(MAX_INT))
-        return MAX_INT;
-
-    return static_cast<int>(deltaMsec);
-}
-
 bool CommonTimeServer::shouldPanicNotGettingGoodData() {
     if (mClient_FirstSyncTX) {
         int64_t now = mLocalClock.getLocalTime();
diff --git a/services/common_time/common_time_server.h b/services/common_time/common_time_server.h
index a0f549f..f6a2419 100644
--- a/services/common_time/common_time_server.h
+++ b/services/common_time/common_time_server.h
@@ -28,6 +28,7 @@
 #include "clock_recovery.h"
 #include "common_clock.h"
 #include "common_time_server_packets.h"
+#include "utils.h"
 
 #define RTT_LOG_SIZE 30
 
@@ -104,18 +105,6 @@
         int64_t rxTimes[RTT_LOG_SIZE];
     };
 
-    class TimeoutHelper {
-      public:
-        TimeoutHelper() : mTimeoutValid(false) { }
-
-        void setTimeout(int msec);
-        int msecTillTimeout();
-
-      private:
-        bool        mTimeoutValid;
-        nsecs_t     mEndTime;
-    };
-
     bool threadLoop();
 
     bool runStateMachine_l();
@@ -194,7 +183,7 @@
     bool shouldPanicNotGettingGoodData();
 
     // Helper to keep track of the state machine's current timeout
-    TimeoutHelper mCurTimeout;
+    Timeout mCurTimeout;
 
     // common clock, local clock abstraction, and clock recovery loop
     CommonClock mCommonClock;
@@ -249,6 +238,11 @@
     // interface AND currently active common clock clients.
     bool mCommonClockHasClients;
 
+    // Internal logs used for dumpsys.
+    LogRing                 mStateChangeLog;
+    LogRing                 mElectionLog;
+    LogRing                 mBadPktLog;
+
     // Configuration info
     struct sockaddr_storage mMasterElectionEP;          // Endpoint over which we conduct master election
     String8                 mBindIface;                 // Endpoint for the service to bind to.
diff --git a/services/common_time/common_time_server_api.cpp b/services/common_time/common_time_server_api.cpp
index fb8c261..e157071 100644
--- a/services/common_time/common_time_server_api.cpp
+++ b/services/common_time/common_time_server_api.cpp
@@ -354,6 +354,9 @@
 
         dump_printf("Active Clients : %u\n", activeClients);
         mClient_PacketRTTLog.dumpLog(fd, mCommonClock);
+        mStateChangeLog.dumpLog(fd);
+        mElectionLog.dumpLog(fd);
+        mBadPktLog.dumpLog(fd);
     }
 
     return NO_ERROR;
diff --git a/services/common_time/utils.cpp b/services/common_time/utils.cpp
new file mode 100644
index 0000000..ed2c77d
--- /dev/null
+++ b/services/common_time/utils.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "common_time"
+#include <utils/Log.h>
+
+#include "utils.h"
+
+namespace android {
+
+void Timeout::setTimeout(int msec) {
+    if (msec < 0) {
+        mSystemEndTime = 0;
+        return;
+    }
+
+    mSystemEndTime = systemTime() + (static_cast<nsecs_t>(msec) * 1000000);
+}
+
+int Timeout::msecTillTimeout(nsecs_t nowTime) {
+    if (!mSystemEndTime) {
+        return -1;
+    }
+
+    if (mSystemEndTime < nowTime) {
+        return 0;
+    }
+
+    nsecs_t delta = mSystemEndTime - nowTime;
+    delta += 999999;
+    delta /= 1000000;
+    if (delta > 0x7FFFFFFF) {
+        return 0x7FFFFFFF;
+    }
+
+    return static_cast<int>(delta);
+}
+
+LogRing::LogRing(const char* header, size_t entries)
+    : mSize(entries)
+    , mWr(0)
+    , mIsFull(false)
+    , mHeader(header) {
+    mRingBuffer = new Entry[mSize];
+    if (NULL == mRingBuffer)
+        ALOGE("Failed to allocate log ring with %u entries.", mSize);
+}
+
+LogRing::~LogRing() {
+    if (NULL != mRingBuffer)
+        delete[] mRingBuffer;
+}
+
+void LogRing::log(int prio, const char* tag, const char* fmt, ...) {
+    va_list argp;
+    va_start(argp, fmt);
+    internalLog(prio, tag, fmt, argp);
+    va_end(argp);
+}
+
+void LogRing::log(const char* fmt, ...) {
+    va_list argp;
+    va_start(argp, fmt);
+    internalLog(0, NULL, fmt, argp);
+    va_end(argp);
+}
+
+void LogRing::internalLog(int prio,
+                          const char* tag,
+                          const char* fmt,
+                          va_list argp) {
+    if (NULL != mRingBuffer) {
+        Mutex::Autolock lock(&mLock);
+        String8 s(String8::formatV(fmt, argp));
+        Entry* last = NULL;
+
+        if (mIsFull || mWr)
+            last = &(mRingBuffer[(mWr + mSize - 1) % mSize]);
+
+
+        if ((NULL != last) && !last->s.compare(s)) {
+            gettimeofday(&(last->last_ts), NULL);
+            ++last->count;
+        } else {
+            gettimeofday(&mRingBuffer[mWr].first_ts, NULL);
+            mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts;
+            mRingBuffer[mWr].count = 1;
+            mRingBuffer[mWr].s.setTo(s);
+
+            mWr = (mWr + 1) % mSize;
+            if (!mWr)
+                mIsFull = true;
+        }
+    }
+
+    if (NULL != tag)
+        LOG_PRI_VA(prio, tag, fmt, argp);
+}
+
+void LogRing::dumpLog(int fd) {
+    if (NULL == mRingBuffer)
+        return;
+
+    Mutex::Autolock lock(&mLock);
+
+    if (!mWr && !mIsFull)
+        return;
+
+    char buf[1024];
+    int res;
+    size_t start = mIsFull ? mWr : 0;
+    size_t count = mIsFull ? mSize : mWr;
+    static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S";
+
+    res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader);
+    if (res > 0)
+        write(fd, buf, res);
+
+    for (size_t i = 0; i < count; ++i) {
+        struct tm t;
+        char timebuf[64];
+        char repbuf[96];
+        size_t ndx = (start + i) % mSize;
+
+        if (1 != mRingBuffer[ndx].count) {
+            localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t);
+            strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
+            snprintf(repbuf, sizeof(repbuf),
+                    " (repeated %d times, last was %s.%03ld)",
+                     mRingBuffer[ndx].count,
+                     timebuf,
+                     mRingBuffer[ndx].last_ts.tv_usec / 1000);
+            repbuf[sizeof(repbuf) - 1] = 0;
+        } else {
+            repbuf[0] = 0;
+        }
+
+        localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
+        strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
+        res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n", 
+                       i, timebuf,
+                       mRingBuffer[ndx].first_ts.tv_usec / 1000,
+                       mRingBuffer[ndx].s.string(),
+                       repbuf);
+
+        if (res > 0)
+            write(fd, buf, res);
+    }
+}
+
+}  // namespace android
diff --git a/services/common_time/utils.h b/services/common_time/utils.h
new file mode 100644
index 0000000..c28cf0a
--- /dev/null
+++ b/services/common_time/utils.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/String8.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Timeout {
+  public:
+    Timeout() : mSystemEndTime(0) { }
+
+    // Set a timeout which should occur msec milliseconds from now.
+    // Negative values will cancel any current timeout;
+    void setTimeout(int msec);
+
+    // Return the number of milliseconds until the timeout occurs, or -1 if
+    // no timeout is scheduled.
+    int msecTillTimeout(nsecs_t nowTime);
+    int msecTillTimeout() { return msecTillTimeout(systemTime()); }
+
+  private:
+    // The systemTime() at which the timeout will be complete, or 0 if no
+    // timeout is currently scheduled.
+    nsecs_t mSystemEndTime;
+};
+
+class LogRing {
+  public:
+    LogRing(const char* header, size_t entries);
+    ~LogRing();
+
+    // Send a log message to logcat as well as storing it in the ring buffer.
+    void log(int prio, const char* tag, const char* fmt, ...);
+
+    // Add a log message the ring buffer, do not send the message to logcat.
+    void log(const char* fmt, ...);
+
+    // Dump the log to an fd (dumpsys style)
+    void dumpLog(int fd);
+
+  private:
+    class Entry {
+      public:
+        uint32_t count;
+        struct timeval first_ts;
+        struct timeval last_ts;
+        String8 s;
+    };
+
+    Mutex  mLock;
+    Entry* mRingBuffer;
+    size_t mSize;
+    size_t mWr;
+    bool   mIsFull;
+    const char* mHeader;
+
+    void internalLog(int prio, const char* tag, const char* fmt, va_list va);
+};
+
+}  // namespace android
+
+#endif  // __UTILS_H__
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index cd6a2ec..6d63998 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2620,7 +2620,6 @@
     dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
     dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
     dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
-    dump.appendFormat(INDENT4 "OrientationCenter: %0.3f\n", mOrientationCenter);
     dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
     dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
     dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
@@ -3051,7 +3050,6 @@
         }
 
         // Orientation
-        mOrientationCenter = 0;
         mOrientationScale = 0;
         if (mHaveTilt) {
             mOrientedRanges.haveOrientation = true;
@@ -3067,10 +3065,13 @@
             if (mCalibration.orientationCalibration
                     == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
                 if (mRawPointerAxes.orientation.valid) {
-                    mOrientationCenter = avg(mRawPointerAxes.orientation.minValue,
-                            mRawPointerAxes.orientation.maxValue);
-                    mOrientationScale = M_PI / (mRawPointerAxes.orientation.maxValue -
-                            mRawPointerAxes.orientation.minValue);
+                    if (mRawPointerAxes.orientation.maxValue > 0) {
+                        mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
+                    } else if (mRawPointerAxes.orientation.minValue < 0) {
+                        mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
+                    } else {
+                        mOrientationScale = 0;
+                    }
                 }
             }
 
@@ -3284,6 +3285,8 @@
             out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
         } else if (sizeCalibrationString == "diameter") {
             out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
+        } else if (sizeCalibrationString == "box") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
         } else if (sizeCalibrationString == "area") {
             out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
         } else if (sizeCalibrationString != "default") {
@@ -3404,6 +3407,9 @@
     case Calibration::SIZE_CALIBRATION_DIAMETER:
         dump.append(INDENT4 "touch.size.calibration: diameter\n");
         break;
+    case Calibration::SIZE_CALIBRATION_BOX:
+        dump.append(INDENT4 "touch.size.calibration: box\n");
+        break;
     case Calibration::SIZE_CALIBRATION_AREA:
         dump.append(INDENT4 "touch.size.calibration: area\n");
         break;
@@ -3954,6 +3960,7 @@
         switch (mCalibration.sizeCalibration) {
         case Calibration::SIZE_CALIBRATION_GEOMETRIC:
         case Calibration::SIZE_CALIBRATION_DIAMETER:
+        case Calibration::SIZE_CALIBRATION_BOX:
         case Calibration::SIZE_CALIBRATION_AREA:
             if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
                 touchMajor = in.touchMajor;
@@ -4050,7 +4057,7 @@
 
             switch (mCalibration.orientationCalibration) {
             case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-                orientation = (in.orientation - mOrientationCenter) * mOrientationScale;
+                orientation = in.orientation * mOrientationScale;
                 break;
             case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
                 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 122a2ab..6c06986 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1162,6 +1162,7 @@
             SIZE_CALIBRATION_NONE,
             SIZE_CALIBRATION_GEOMETRIC,
             SIZE_CALIBRATION_DIAMETER,
+            SIZE_CALIBRATION_BOX,
             SIZE_CALIBRATION_AREA,
         };
 
@@ -1294,7 +1295,6 @@
 
     float mSizeScale;
 
-    float mOrientationCenter;
     float mOrientationScale;
 
     float mDistanceScale;
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index f9c432b..77b3b50 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -210,11 +210,19 @@
 
             synchronized (mAppWidgetIds) {
                 ensureStateLoadedLocked();
-                int N = mInstalledProviders.size();
+                // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
+                // list of installed providers and skip providers that we don't need to update.
+                // Also note that remove the provider does not clear the Provider component data.
+                ArrayList<Provider> installedProviders =
+                        new ArrayList<Provider>(mInstalledProviders);
+                HashSet<ComponentName> removedProviders = new HashSet<ComponentName>();
+                int N = installedProviders.size();
                 for (int i = N - 1; i >= 0; i--) {
-                    Provider p = mInstalledProviders.get(i);
-                    String pkgName = p.info.provider.getPackageName();
-                    updateProvidersForPackageLocked(pkgName);
+                    Provider p = installedProviders.get(i);
+                    ComponentName cn = p.info.provider;
+                    if (!removedProviders.contains(cn)) {
+                        updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
+                    }
                 }
                 saveStateLocked();
             }
@@ -225,6 +233,7 @@
         final String action = intent.getAction();
         boolean added = false;
         boolean changed = false;
+        boolean providersModified = false;
         String pkgList[] = null;
         if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
             pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -256,12 +265,12 @@
                         || (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
                     for (String pkgName : pkgList) {
                         // The package was just upgraded
-                        updateProvidersForPackageLocked(pkgName);
+                        providersModified |= updateProvidersForPackageLocked(pkgName, null);
                     }
                 } else {
                     // The package was just added
                     for (String pkgName : pkgList) {
-                        addProvidersForPackageLocked(pkgName);
+                        providersModified |= addProvidersForPackageLocked(pkgName);
                     }
                 }
                 saveStateLocked();
@@ -274,12 +283,20 @@
                 synchronized (mAppWidgetIds) {
                     ensureStateLoadedLocked();
                     for (String pkgName : pkgList) {
-                        removeProvidersForPackageLocked(pkgName);
+                        providersModified |= removeProvidersForPackageLocked(pkgName);
                         saveStateLocked();
                     }
                 }
             }
         }
+
+        if (providersModified) {
+            // If the set of providers has been modified, notify each active AppWidgetHost
+            synchronized (mAppWidgetIds) {
+                ensureStateLoadedLocked();
+                notifyHostsForProvidersChangedLocked();
+            }
+        }
     }
 
     private void dumpProvider(Provider p, int index, PrintWriter pw) {
@@ -1642,7 +1659,8 @@
         getSettingsFile(mUserId).delete();
     }
 
-    void addProvidersForPackageLocked(String pkgName) {
+    boolean addProvidersForPackageLocked(String pkgName) {
+        boolean providersAdded = false;
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         intent.setPackage(pkgName);
         List<ResolveInfo> broadcastReceivers;
@@ -1652,7 +1670,7 @@
                     PackageManager.GET_META_DATA, mUserId);
         } catch (RemoteException re) {
             // Shouldn't happen, local call
-            return;
+            return false;
         }
         final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
         for (int i = 0; i < N; i++) {
@@ -1663,11 +1681,21 @@
             }
             if (pkgName.equals(ai.packageName)) {
                 addProviderLocked(ri);
+                providersAdded = true;
             }
         }
+
+        return providersAdded;
     }
 
-    void updateProvidersForPackageLocked(String pkgName) {
+    /**
+     * Updates all providers with the specified package names, and records any providers that were
+     * pruned.
+     *
+     * @return whether any providers were updated
+     */
+    boolean updateProvidersForPackageLocked(String pkgName, Set<ComponentName> removedProviders) {
+        boolean providersUpdated = false;
         HashSet<String> keep = new HashSet<String>();
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         intent.setPackage(pkgName);
@@ -1678,7 +1706,7 @@
                 PackageManager.GET_META_DATA, mUserId);
         } catch (RemoteException re) {
             // Shouldn't happen, local call
-            return;
+            return false;
         }
 
         // add the missing ones and collect which ones to keep
@@ -1695,6 +1723,7 @@
                 if (p == null) {
                     if (addProviderLocked(ri)) {
                         keep.add(ai.name);
+                        providersUpdated = true;
                     }
                 } else {
                     Provider parsed = parseProviderInfoXml(component, ri);
@@ -1729,6 +1758,7 @@
                             }
                             // Now that we've told the host, push out an update.
                             sendUpdateIntentLocked(p, appWidgetIds);
+                            providersUpdated = true;
                         }
                     }
                 }
@@ -1741,17 +1771,25 @@
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())
                     && !keep.contains(p.info.provider.getClassName())) {
+                if (removedProviders != null) {
+                    removedProviders.add(p.info.provider);
+                }
                 removeProviderLocked(i, p);
+                providersUpdated = true;
             }
         }
+
+        return providersUpdated;
     }
 
-    void removeProvidersForPackageLocked(String pkgName) {
+    boolean removeProvidersForPackageLocked(String pkgName) {
+        boolean providersRemoved = false;
         int N = mInstalledProviders.size();
         for (int i = N - 1; i >= 0; i--) {
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())) {
                 removeProviderLocked(i, p);
+                providersRemoved = true;
             }
         }
 
@@ -1766,5 +1804,24 @@
                 deleteHostLocked(host);
             }
         }
+
+        return providersRemoved;
+    }
+
+    void notifyHostsForProvidersChangedLocked() {
+        final int N = mHosts.size();
+        for (int i = N - 1; i >= 0; i--) {
+            Host host = mHosts.get(i);
+            try {
+                if (host.callbacks != null) {
+                    host.callbacks.providersChanged();
+                }
+            } catch (RemoteException ex) {
+                // It failed; remove the callback. No need to prune because
+                // we know that this host is still referenced by this
+                // instance.
+                host.callbacks = null;
+            }
+        }
     }
 }
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index ab9ae69..0a6f23c 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -68,7 +68,7 @@
  * a degree Centigrade</p>
  * <p>&quot;technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
  */
-class BatteryService extends Binder {
+public class BatteryService extends Binder {
     private static final String TAG = BatteryService.class.getSimpleName();
 
     private static final boolean LOCAL_LOGV = false;
@@ -148,12 +148,12 @@
         update();
     }
 
-    final boolean isPowered() {
+    public final boolean isPowered() {
         // assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
         return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
     }
 
-    final boolean isPowered(int plugTypeSet) {
+    public final boolean isPowered(int plugTypeSet) {
         // assume we are powered if battery state is unknown so
         // the "stay on while plugged in" option will work.
         if (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
@@ -172,7 +172,7 @@
         return (plugTypeSet & plugTypeBit) != 0;
     }
 
-    final int getPlugType() {
+    public final int getPlugType() {
         return mPlugType;
     }
 
@@ -195,7 +195,7 @@
     };
 
     // returns battery level as a percentage
-    final int getBatteryLevel() {
+    public final int getBatteryLevel() {
         return mBatteryLevel;
     }
 
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
new file mode 100644
index 0000000..cc9b9fa
--- /dev/null
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -0,0 +1,696 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+package com.android.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothManager;
+import android.bluetooth.IBluetoothManagerCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
+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.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+import java.util.List;
+import java.util.ArrayList;
+class BluetoothManagerService extends IBluetoothManager.Stub {
+    private static final String TAG = "BluetoothManagerService";
+    private static final boolean DBG = true;
+
+    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
+    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+    private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
+    private static final String EXTRA_ACTION="action";
+    private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
+    private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
+    private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
+    private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
+
+    private static final int MESSAGE_ENABLE = 1;
+    private static final int MESSAGE_DISABLE = 2;
+    private static final int MESSAGE_REGISTER_ADAPTER = 20;
+    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
+    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
+    private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
+    private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
+    private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
+    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60;
+    private static final int MESSAGE_TIMEOUT_BIND =100;
+    private static final int MESSAGE_TIMEOUT_UNBIND =101;
+    private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
+    private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
+    private static final int MAX_SAVE_RETRIES=3;
+
+    private final Context mContext;
+
+    // Locks are not provided for mName and mAddress.
+    // They are accessed in handler or broadcast receiver, same thread context.
+    private String mAddress;
+    private String mName;
+    private final ContentResolver mContentResolver;
+    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
+    private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
+    private IBluetooth mBluetooth;
+    private boolean mBinding;
+    private boolean mUnbinding;
+
+    private void registerForAirplaneMode(IntentFilter filter) {
+        final ContentResolver resolver = mContext.getContentResolver();
+        final String airplaneModeRadios = Settings.System.getString(resolver,
+                Settings.System.AIRPLANE_MODE_RADIOS);
+        final String toggleableRadios = Settings.System.getString(resolver,
+                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true :
+                airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
+        if (mIsAirplaneSensitive) {
+            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        }
+    }
+
+    private final IBluetoothCallback mBluetoothCallback =  new IBluetoothCallback.Stub() {
+        @Override
+        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {
+            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
+            mHandler.sendMessage(msg);
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
+                String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
+                if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName);
+                if (newName != null) {
+                    storeNameAndAddress(newName, null);
+                }
+            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
+                if (isAirplaneModeOn()) {
+                        // disable without persisting the setting
+                        handleDisable(false);
+                } else {
+                    if (isBluetoothPersistedStateOn()) {
+                        // enable without persisting the setting
+                        handleEnable(false);
+                    }
+                }
+            }
+        }
+    };
+
+    BluetoothManagerService(Context context) {
+        mContext = context;
+        mBluetooth = null;
+        mBinding = false;
+        mUnbinding = false;
+        mAddress = null;
+        mName = null;
+        mContentResolver = context.getContentResolver();
+        mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
+        mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
+        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
+        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+        registerForAirplaneMode(filter);
+        mContext.registerReceiver(mReceiver, filter);
+        boolean airplaneModeOn = isAirplaneModeOn();
+        boolean bluetoothOn = isBluetoothPersistedStateOn();
+        loadStoredNameAndAddress();
+        if (DBG) Log.d(TAG, "airplaneModeOn: " + airplaneModeOn + " bluetoothOn: " + bluetoothOn);
+        if (bluetoothOn) {
+            //Enable
+            if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
+            enable();
+        } else if (!isNameAndAddressSet()) {
+            //Sync the Bluetooth name and address from the Bluetooth Adapter
+            if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
+            getNameAndAddress();
+        }
+    }
+
+    /**
+     *  Returns true if airplane mode is currently on
+     */
+    private final boolean isAirplaneModeOn() {
+        return Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
+    }
+
+    /**
+     *  Returns true if the Bluetooth saved state is "on"
+     */
+    private final boolean isBluetoothPersistedStateOn() {
+        return Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.BLUETOOTH_ON, 0) ==1;
+    }
+
+    /**
+     *  Save the Bluetooth on/off state
+     *
+     */
+    private void persistBluetoothSetting(boolean setOn) {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                               Settings.Secure.BLUETOOTH_ON,
+                               setOn ? 1 : 0);
+    }
+
+    /**
+     * Returns true if the Bluetooth Adapter's name and address is
+     * locally cached
+     * @return
+     */
+    private boolean isNameAndAddressSet() {
+        return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0;
+    }
+
+    /**
+     * Retrieve the Bluetooth Adapter's name and address and save it in
+     * in the local cache
+     */
+    private void loadStoredNameAndAddress() {
+        if (DBG) Log.d(TAG, "Loading stored name and address");
+        mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
+        mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
+        if (mName == null || mAddress == null) {
+            if (DBG) Log.d(TAG, "Name or address not cached...");
+        }
+    }
+
+    /**
+     * Save the Bluetooth name and address in the persistent store.
+     * Only non-null values will be saved.
+     * @param name
+     * @param address
+     */
+    private void storeNameAndAddress(String name, String address) {
+        if (name != null) {
+            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
+            mName = name;
+            if (DBG) Log.d(TAG,"Stored Bluetooth name: " +
+                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
+        }
+
+        if (address != null) {
+            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
+            mAddress=address;
+            if (DBG)  Log.d(TAG,"Stored Bluetoothaddress: " +
+                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
+        }
+    }
+
+    public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+        synchronized(mConnection) {
+            return mBluetooth;
+        }
+    }
+
+    public void unregisterAdapter(IBluetoothManagerCallback callback) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+    }
+
+    public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+    }
+
+    public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+    }
+
+    public boolean isEnabled() {
+        synchronized(mConnection) {
+            try {
+                return (mBluetooth != null && mBluetooth.isEnabled());
+            } catch (RemoteException e) {
+                Log.e(TAG, "isEnabled()", e);
+            }
+        }
+        return false;
+    }
+
+    public void getNameAndAddress() {
+        if (DBG) {
+            Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth +
+                  " mBinding = " + mBinding);
+        }
+        synchronized(mConnection) {
+            if (mBinding) return;
+            if (mConnection == null) mBinding = true;
+        }
+        Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+        mHandler.sendMessage(msg);
+    }
+
+    public boolean enable() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+        if (DBG) {
+            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
+                    " mBinding = " + mBinding);
+        }
+
+        synchronized(mConnection) {
+            if (mBinding) {
+                Log.w(TAG,"enable(): binding in progress. Returning..");
+                return true;
+            }
+            if (mConnection == null) mBinding = true;
+        }
+
+        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+        msg.arg1=1; //persist
+        mHandler.sendMessage(msg);
+        return true;
+    }
+
+    public boolean disable(boolean persist) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
+        if (DBG) {
+            Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
+                " mBinding = " + mBinding);
+        }
+
+        synchronized(mConnection) {
+             if (mBluetooth == null) return false;
+        }
+        Message msg = mHandler.obtainMessage(MESSAGE_DISABLE);
+        msg.arg1=(persist?1:0);
+        mHandler.sendMessage(msg);
+        return true;
+    }
+
+    public void unbindAndFinish() {
+        if (DBG) {
+            Log.d(TAG,"unbindAndFinish(): " + mBluetooth +
+                " mBinding = " + mBinding);
+        }
+
+        synchronized (mConnection) {
+            if (mUnbinding) return;
+            mUnbinding = true;
+            if (mConnection != null) {
+                if (!mConnection.isGetNameAddressOnly()) {
+                    //Unregister callback object
+                    try {
+                        mBluetooth.unregisterCallback(mBluetoothCallback);
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Unable to register BluetoothCallback",re);
+                    }
+                }
+                if (DBG) Log.d(TAG, "Sending unbind request.");
+                mBluetooth = null;
+                //Unbind
+                mContext.unbindService(mConnection);
+                mUnbinding = false;
+            } else {
+                mUnbinding=false;
+            }
+        }
+    }
+
+    private void sendBluetoothStateCallback(boolean isUp) {
+        int n = mStateChangeCallbacks.beginBroadcast();
+        if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
+        for (int i=0; i <n;i++) {
+            try {
+                mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
+            }
+        }
+        mStateChangeCallbacks.finishBroadcast();
+    }
+
+    /**
+     * Inform BluetoothAdapter instances that Adapter service is down
+     */
+    private void sendBluetoothServiceDownCallback() {
+        if (!mConnection.isGetNameAddressOnly()) {
+            if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks");
+            int n = mCallbacks.beginBroadcast();
+            Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
+            for (int i=0; i <n;i++) {
+                try {
+                    mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
+                }  catch (RemoteException e) {
+                    Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
+                }
+            }
+            mCallbacks.finishBroadcast();
+        }
+    }
+    public String getAddress() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+        synchronized(mConnection) {
+            if (mBluetooth != null) {
+                try {
+                    return mBluetooth.getAddress();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e);
+                }
+            }
+        }
+        // mAddress is accessed from outside.
+        // It is alright without a lock. Here, bluetooth is off, no other thread is
+        // changing mAddress
+        return mAddress;
+    }
+
+    public String getName() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+        synchronized(mConnection) {
+            if (mBluetooth != null) {
+                try {
+                    return mBluetooth.getName();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e);
+                }
+            }
+        }
+        // mName is accessed from outside.
+        // It alright without a lock. Here, bluetooth is off, no other thread is
+        // changing mName
+        return mName;
+    }
+
+    private class BluetoothServiceConnection implements ServiceConnection {
+
+        private boolean mGetNameAddressOnly;
+
+        public void setGetNameAddressOnly(boolean getOnly) {
+            mGetNameAddressOnly = getOnly;
+        }
+
+        public boolean isGetNameAddressOnly() {
+            return mGetNameAddressOnly;
+        }
+
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService");
+            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
+            msg.obj = service;
+            mHandler.sendMessage(msg);
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            // Called if we unexpected disconnected.
+            if (DBG) Log.d(TAG, "BluetoothServiceConnection: disconnected from AdapterService");
+            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (DBG) Log.d (TAG, "Message: " + msg.what);
+            switch (msg.what) {
+                case MESSAGE_GET_NAME_AND_ADDRESS: {
+                    if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS");
+                    synchronized(mConnection) {
+                        //Start bind request
+                        if (mBluetooth == null) {
+                            if (DBG) Log.d(TAG, "Binding to service to get name and address");
+                            mConnection.setGetNameAddressOnly(true);
+                            //Start bind timeout and bind
+                            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
+                            mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
+                            Intent i = new Intent(IBluetooth.class.getName());
+                            if (!mContext.bindService(i, mConnection,
+                                                  Context.BIND_AUTO_CREATE)) {
+                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                                Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
+                            }
+                        }
+                        else {
+                            Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+                            mHandler.sendMessage(saveMsg);
+                        }
+                    }
+                    break;
+                }
+                case MESSAGE_SAVE_NAME_AND_ADDRESS: {
+                    if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
+                    synchronized(mConnection) {
+                        if (mBluetooth != null) {
+                            String name =  null;
+                            String address = null;
+                            try {
+                                name =  mBluetooth.getName();
+                                address = mBluetooth.getAddress();
+                            } catch (RemoteException re) {
+                                Log.e(TAG,"",re);
+                            }
+
+                            if (name != null && address != null) {
+                                storeNameAndAddress(name,address);
+                                sendBluetoothServiceDownCallback();
+                                unbindAndFinish();
+                            } else {
+                                if (msg.arg1 < MAX_SAVE_RETRIES) {
+                                    Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+                                    retryMsg.arg1= 1+msg.arg1;
+                                    if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1);
+                                    mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
+                                } else {
+                                    Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
+                                    sendBluetoothServiceDownCallback();
+                                    unbindAndFinish();
+                                }
+                            }
+                        }
+                    }
+                    break;
+                }
+                case MESSAGE_ENABLE:
+                    if (DBG) {
+                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
+                    }
+
+                    handleEnable(msg.arg1 == 1);
+                    break;
+
+                case MESSAGE_DISABLE:
+                    handleDisable(msg.arg1 == 1);
+                    break;
+
+                case MESSAGE_REGISTER_ADAPTER:
+                {
+                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
+                    boolean added = mCallbacks.register(callback);
+                    Log.d(TAG,"Added callback: " +  (callback == null? "null": callback)  +":" +added );
+                }
+                    break;
+                case MESSAGE_UNREGISTER_ADAPTER:
+                {
+                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
+                    boolean removed = mCallbacks.unregister(callback);
+                    Log.d(TAG,"Removed callback: " +  (callback == null? "null": callback)  +":" + removed);
+                    break;
+                }
+                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
+                {
+                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
+                    mStateChangeCallbacks.register(callback);
+                    break;
+                }
+                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
+                {
+                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
+                    mStateChangeCallbacks.unregister(callback);
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
+                {
+                    if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
+
+                    //Remove timeout
+                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+
+                    IBinder service = (IBinder) msg.obj;
+                    synchronized(mConnection) {
+                        mBinding = false;
+                        mBluetooth = IBluetooth.Stub.asInterface(service);
+
+                        if (mConnection.isGetNameAddressOnly()) {
+                            //Request GET NAME AND ADDRESS
+                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+                            mHandler.sendMessage(getMsg);
+                            return;
+                        }
+
+                        //Register callback object
+                        try {
+                            mBluetooth.registerCallback(mBluetoothCallback);
+                        } catch (RemoteException re) {
+                            Log.e(TAG, "Unable to register BluetoothCallback",re);
+                        }
+
+                        //Inform BluetoothAdapter instances that service is up
+                        int n = mCallbacks.beginBroadcast();
+                        Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+                        for (int i=0; i <n;i++) {
+                            try {
+                                mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+                            }
+                        }
+                        mCallbacks.finishBroadcast();
+
+                        //Do enable request
+                        try {
+                            if(!mBluetooth.enable()) {
+                                Log.e(TAG,"IBluetooth.enable() returned false");
+                            }
+                        } catch (RemoteException e) {
+                            Log.e(TAG,"Unable to call enable()",e);
+                        }
+                    }
+
+                    break;
+                }
+                case MESSAGE_TIMEOUT_BIND: {
+                    Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
+                    synchronized(mConnection) {
+                        mBinding = false;
+                    }
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_STATE_CHANGE:
+                {
+                    int prevState = msg.arg1;
+                    int newState = msg.arg2;
+                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
+                    if (prevState != newState) {
+                        //Notify all proxy objects first of adapter state change
+                        if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) {
+                            boolean isUp = (newState==BluetoothAdapter.STATE_ON);
+                            sendBluetoothStateCallback(isUp);
+
+                            //If Bluetooth is off, send service down event to proxy objects, and unbind
+                            if (!isUp) {
+                                sendBluetoothServiceDownCallback();
+                                unbindAndFinish();
+                            }
+                        }
+
+                        //Send broadcast message to everyone else
+                        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+                        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
+                        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
+                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
+                        mContext.sendBroadcast(intent,BLUETOOTH_PERM);
+                    }
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
+                {
+                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
+                    sendBluetoothServiceDownCallback();
+                    break;
+                }
+                case MESSAGE_TIMEOUT_UNBIND:
+                {
+                    Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
+                    synchronized(mConnection) {
+                        mUnbinding = false;
+                    }
+                    break;
+                }
+            }
+        }
+    };
+
+    private void handleEnable(boolean persist) {
+        if (persist) {
+            persistBluetoothSetting(true);
+        }
+
+        synchronized(mConnection) {
+            if (mBluetooth == null) {
+                //Start bind timeout and bind
+                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
+                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
+                mConnection.setGetNameAddressOnly(false);
+                Intent i = new Intent(IBluetooth.class.getName());
+                if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE)) {
+                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                    Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
+                }
+            } else {
+                //Check if name and address is loaded if not get it first.
+                if (!isNameAndAddressSet()) {
+                    try {
+                        if (DBG) Log.d(TAG,"Getting and storing Bluetooth name and address prior to enable.");
+                        storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress());
+                    } catch (RemoteException e) {Log.e(TAG, "", e);};
+                }
+
+                //Enable bluetooth
+                try {
+                    if(!mBluetooth.enable()) {
+                        Log.e(TAG,"IBluetooth.enable() returned false");
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG,"Unable to call enable()",e);
+                }
+            }
+        }
+    }
+
+    private void handleDisable(boolean persist) {
+        synchronized(mConnection) {
+            if (mBluetooth != null ) {
+                if (persist) {
+                    persistBluetoothSetting(false);
+                }
+                mConnection.setGetNameAddressOnly(false);
+                if (DBG) Log.d(TAG,"Sending off request.");
+
+                try {
+                    if(!mBluetooth.disable()) {
+                        Log.e(TAG,"IBluetooth.disable() returned false");
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG,"Unable to call disable()",e);
+                }
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/CommonTimeManagementService.java b/services/java/com/android/server/CommonTimeManagementService.java
index 9a25d2e..c316733 100644
--- a/services/java/com/android/server/CommonTimeManagementService.java
+++ b/services/java/com/android/server/CommonTimeManagementService.java
@@ -120,6 +120,8 @@
             reevaluateServiceState();
         }
         public void limitReached(String limitName, String iface) { }
+
+        public void interfaceClassDataActivityChanged(String label, boolean active) {}
     };
 
     private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 230f07b..9f93901 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
@@ -35,6 +36,7 @@
 import android.net.DummyDataStateTracker;
 import android.net.EthernetDataTracker;
 import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
@@ -546,6 +548,13 @@
         mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
         mSettingsObserver.observe(mContext);
 
+        INetworkManagementEventObserver netdObserver = new NetdObserver();
+        try {
+            mNetd.registerObserver(netdObserver);
+        } catch (RemoteException e) {
+            loge("Error registering observer :" + e);
+        }
+
         loadGlobalProxy();
     }
 private NetworkStateTracker makeWimaxStateTracker() {
@@ -923,6 +932,19 @@
         return tracker != null && tracker.setRadio(turnOn);
     }
 
+    private class NetdObserver extends INetworkManagementEventObserver.Stub {
+        public void interfaceClassDataActivityChanged(String label, boolean active) {
+            int deviceType = Integer.parseInt(label);
+            sendDataActivityBroadcast(deviceType, active);
+        }
+
+        public void interfaceStatusChanged(String iface, boolean up) {}
+        public void interfaceLinkStateChanged(String iface, boolean up) {}
+        public void interfaceAdded(String iface) {}
+        public void interfaceRemoved(String iface) {}
+        public void limitReached(String limitName, String iface) {}
+    }
+
     /**
      * Used to notice when the calling process dies so we can self-expire
      *
@@ -1759,6 +1781,13 @@
         sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
     }
 
+    private void sendDataActivityBroadcast(int deviceType, boolean active) {
+        Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
+        intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
+        intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
+        mContext.sendOrderedBroadcast(intent, RECEIVE_DATA_ACTIVITY_CHANGE);
+    }
+
     /**
      * Called when an attempt to fail over to another network has failed.
      * @param info the {@link NetworkInfo} for the failed network
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 0ed5189..9231674 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -16,6 +16,9 @@
 
 package com.android.server;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -24,6 +27,7 @@
 import android.content.Intent;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileObserver;
@@ -36,8 +40,10 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.text.format.Formatter;
 import android.util.EventLog;
 import android.util.Slog;
+import android.util.TimeUtils;
 
 /**
  * This class implements a service to monitor the amount of disk
@@ -71,6 +77,7 @@
     private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
     private static final int DEFAULT_FULL_THRESHOLD_BYTES = 1024*1024; // 1MB
     private long mFreeMem;  // on /data
+    private long mFreeMemAfterLastCacheClear;  // on /data
     private long mLastReportedFreeMem;
     private long mLastReportedFreeMemTime;
     private boolean mLowMemFlag=false;
@@ -95,7 +102,19 @@
     private final CacheFileDeletedObserver mCacheFileDeletedObserver;
     private static final int _TRUE = 1;
     private static final int _FALSE = 0;
+    // This is the raw threshold that has been set at which we consider
+    // storage to be low.
     private long mMemLowThreshold;
+    // This is the threshold at which we start trying to flush caches
+    // to get below the low threshold limit.  It is less than the low
+    // threshold; we will allow storage to get a bit beyond the limit
+    // before flushing and checking if we are actually low.
+    private long mMemCacheStartTrimThreshold;
+    // This is the threshold that we try to get to when deleting cache
+    // files.  This is greater than the low threshold so that we will flush
+    // more files than absolutely needed, to reduce the frequency that
+    // flushing takes place.
+    private long mMemCacheTrimToThreshold;
     private int mMemFullThreshold;
 
     /**
@@ -190,7 +209,7 @@
         try {
             if (localLOGV) Slog.i(TAG, "Clearing cache");
             IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
-                    freeStorageAndNotify(mMemLowThreshold, mClearCacheObserver);
+                    freeStorageAndNotify(mMemCacheTrimToThreshold, mClearCacheObserver);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
             mClearingCache = false;
@@ -216,24 +235,42 @@
 
             //post intent to NotificationManager to display icon if necessary
             if (mFreeMem < mMemLowThreshold) {
-                if (!mLowMemFlag) {
-                    if (checkCache) {
-                        // See if clearing cache helps
-                        // Note that clearing cache is asynchronous and so we do a
-                        // memory check again once the cache has been cleared.
-                        mThreadStartTime = System.currentTimeMillis();
-                        mClearSucceeded = false;
-                        clearCache();
-                    } else {
+                if (checkCache) {
+                    // We are allowed to clear cache files at this point to
+                    // try to get down below the limit, because this is not
+                    // the initial call after a cache clear has been attempted.
+                    // In this case we will try a cache clear if our free
+                    // space has gone below the cache clear limit.
+                    if (mFreeMem < mMemCacheStartTrimThreshold) {
+                        // We only clear the cache if the free storage has changed
+                        // a significant amount since the last time.
+                        if ((mFreeMemAfterLastCacheClear-mFreeMem)
+                                >= ((mMemLowThreshold-mMemCacheStartTrimThreshold)/4)) {
+                            // See if clearing cache helps
+                            // Note that clearing cache is asynchronous and so we do a
+                            // memory check again once the cache has been cleared.
+                            mThreadStartTime = System.currentTimeMillis();
+                            mClearSucceeded = false;
+                            clearCache();
+                        }
+                    }
+                } else {
+                    // This is a call from after clearing the cache.  Note
+                    // the amount of free storage at this point.
+                    mFreeMemAfterLastCacheClear = mFreeMem;
+                    if (!mLowMemFlag) {
+                        // We tried to clear the cache, but that didn't get us
+                        // below the low storage limit.  Tell the user.
                         Slog.i(TAG, "Running low on memory. Sending notification");
                         sendNotification();
                         mLowMemFlag = true;
+                    } else {
+                        if (localLOGV) Slog.v(TAG, "Running low on memory " +
+                                "notification already sent. do nothing");
                     }
-                } else {
-                    if (localLOGV) Slog.v(TAG, "Running low on memory " +
-                            "notification already sent. do nothing");
                 }
             } else {
+                mFreeMemAfterLastCacheClear = mFreeMem;
                 if (mLowMemFlag) {
                     Slog.i(TAG, "Memory available. Cancelling notification");
                     cancelNotification();
@@ -276,7 +313,7 @@
                               Settings.Secure.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                               DEFAULT_THRESHOLD_PERCENTAGE);
         if(localLOGV) Slog.v(TAG, "Threshold Percentage="+value);
-        value *= mTotalMemory;
+        value = (value*mTotalMemory)/100;
         long maxValue = Settings.Secure.getInt(
                 mContentResolver,
                 Settings.Secure.SYS_STORAGE_THRESHOLD_MAX_BYTES,
@@ -312,8 +349,8 @@
         mSystemFileStats = new StatFs(SYSTEM_PATH);
         mCacheFileStats = new StatFs(CACHE_PATH);
         //initialize total storage on device
-        mTotalMemory = ((long)mDataFileStats.getBlockCount() *
-                        mDataFileStats.getBlockSize())/100L;
+        mTotalMemory = (long)mDataFileStats.getBlockCount() *
+                        mDataFileStats.getBlockSize();
         mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
         mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
@@ -325,6 +362,10 @@
         // cache storage thresholds
         mMemLowThreshold = getMemThreshold();
         mMemFullThreshold = getMemFullThreshold();
+        mMemCacheStartTrimThreshold = ((mMemLowThreshold*3)+mMemFullThreshold)/4;
+        mMemCacheTrimToThreshold = mMemLowThreshold
+                + ((mMemLowThreshold-mMemCacheStartTrimThreshold)*2);
+        mFreeMemAfterLastCacheClear = mTotalMemory;
         checkMemory(true);
 
         mCacheFileDeletedObserver = new CacheFileDeletedObserver();
@@ -435,4 +476,40 @@
             EventLogTags.writeCacheFileDeleted(path);
         }
     }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+
+            pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("Current DeviceStorageMonitor state:");
+        pw.print("  mFreeMem="); pw.print(Formatter.formatFileSize(mContext, mFreeMem));
+                pw.print(" mTotalMemory=");
+                pw.println(Formatter.formatFileSize(mContext, mTotalMemory));
+        pw.print("  mFreeMemAfterLastCacheClear=");
+                pw.println(Formatter.formatFileSize(mContext, mFreeMemAfterLastCacheClear));
+        pw.print("  mLastReportedFreeMem=");
+                pw.print(Formatter.formatFileSize(mContext, mLastReportedFreeMem));
+                pw.print(" mLastReportedFreeMemTime=");
+                TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
+                pw.println();
+        pw.print("  mLowMemFlag="); pw.print(mLowMemFlag);
+                pw.print(" mMemFullFlag="); pw.println(mMemFullFlag);
+        pw.print("  mClearSucceeded="); pw.print(mClearSucceeded);
+                pw.print(" mClearingCache="); pw.println(mClearingCache);
+        pw.print("  mMemLowThreshold=");
+                pw.print(Formatter.formatFileSize(mContext, mMemLowThreshold));
+                pw.print(" mMemFullThreshold=");
+                pw.println(Formatter.formatFileSize(mContext, mMemFullThreshold));
+        pw.print("  mMemCacheStartTrimThreshold=");
+                pw.print(Formatter.formatFileSize(mContext, mMemCacheStartTrimThreshold));
+                pw.print(" mMemCacheTrimToThreshold=");
+                pw.println(Formatter.formatFileSize(mContext, mMemCacheTrimToThreshold));
+    }
 }
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 64789d3..e7dac72 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import com.android.server.power.PowerManagerService;
+
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ContentResolver;
@@ -30,7 +32,6 @@
 import android.os.SystemClock;
 import android.os.UEventObserver;
 import android.provider.Settings;
-import android.server.BluetoothService;
 import android.util.Log;
 import android.util.Slog;
 
@@ -148,7 +149,8 @@
                         intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
 
                         // Check if this is Bluetooth Dock
-                        String address = BluetoothService.readDockBluetoothAddress();
+                        // TODO(BT): Get Dock address.
+                        String address = null;
                         if (address != null)
                             intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
                                     BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 41f7335..dd50beb 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -114,6 +114,8 @@
 # Package Manager ready:
 3100 boot_progress_pms_ready (time|2|3)
 # + check activity_launch_time for Home app
+# Value of "unknown sources" setting at app install time
+3110 unknown_sources_enabled (value|1)
 
 
 # ---------------------------
diff --git a/services/java/com/android/server/LightsService.java b/services/java/com/android/server/LightsService.java
index 1e95f3e..89bfcac 100644
--- a/services/java/com/android/server/LightsService.java
+++ b/services/java/com/android/server/LightsService.java
@@ -31,29 +31,29 @@
     private static final String TAG = "LightsService";
     private static final boolean DEBUG = false;
 
-    static final int LIGHT_ID_BACKLIGHT = 0;
-    static final int LIGHT_ID_KEYBOARD = 1;
-    static final int LIGHT_ID_BUTTONS = 2;
-    static final int LIGHT_ID_BATTERY = 3;
-    static final int LIGHT_ID_NOTIFICATIONS = 4;
-    static final int LIGHT_ID_ATTENTION = 5;
-    static final int LIGHT_ID_BLUETOOTH = 6;
-    static final int LIGHT_ID_WIFI = 7;
-    static final int LIGHT_ID_COUNT = 8;
+    public static final int LIGHT_ID_BACKLIGHT = 0;
+    public static final int LIGHT_ID_KEYBOARD = 1;
+    public static final int LIGHT_ID_BUTTONS = 2;
+    public static final int LIGHT_ID_BATTERY = 3;
+    public static final int LIGHT_ID_NOTIFICATIONS = 4;
+    public static final int LIGHT_ID_ATTENTION = 5;
+    public static final int LIGHT_ID_BLUETOOTH = 6;
+    public static final int LIGHT_ID_WIFI = 7;
+    public static final int LIGHT_ID_COUNT = 8;
 
-    static final int LIGHT_FLASH_NONE = 0;
-    static final int LIGHT_FLASH_TIMED = 1;
-    static final int LIGHT_FLASH_HARDWARE = 2;
+    public static final int LIGHT_FLASH_NONE = 0;
+    public static final int LIGHT_FLASH_TIMED = 1;
+    public static final int LIGHT_FLASH_HARDWARE = 2;
 
     /**
      * Light brightness is managed by a user setting.
      */
-    static final int BRIGHTNESS_MODE_USER = 0;
+    public static final int BRIGHTNESS_MODE_USER = 0;
 
     /**
      * Light brightness is managed by a light sensor.
      */
-    static final int BRIGHTNESS_MODE_SENSOR = 1;
+    public static final int BRIGHTNESS_MODE_SENSOR = 1;
 
     private final Light mLights[] = new Light[LIGHT_ID_COUNT];
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 2918dbc..1498a11 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -19,18 +19,13 @@
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.Signature;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.location.Address;
@@ -46,7 +41,6 @@
 import android.location.LocationProvider;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -58,14 +52,15 @@
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.provider.Settings;
+import android.provider.Settings.NameValueTable;
 import android.util.Log;
 import android.util.Slog;
 import android.util.PrintWriterPrinter;
 
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.location.GpsNetInitiatedHandler;
 
 import com.android.server.location.GeocoderProxy;
+import com.android.server.location.GeofenceManager;
 import com.android.server.location.GpsLocationProvider;
 import com.android.server.location.LocationProviderInterface;
 import com.android.server.location.LocationProviderProxy;
@@ -95,9 +90,6 @@
     private static final String TAG = "LocationManagerService";
     private static final boolean LOCAL_LOGV = false;
 
-    // The last time a location was written, by provider name.
-    private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
-
     private static final String ACCESS_FINE_LOCATION =
         android.Manifest.permission.ACCESS_FINE_LOCATION;
     private static final String ACCESS_COARSE_LOCATION =
@@ -147,7 +139,7 @@
     private final static String WAKELOCK_KEY = "LocationManagerService";
     private PowerManager.WakeLock mWakeLock = null;
     private int mPendingBroadcasts;
-    
+
     /**
      * List of all receivers.
      */
@@ -179,13 +171,7 @@
      */
     private final WorkSource mTmpWorkSource = new WorkSource();
 
-    // Proximity listeners
-    private Receiver mProximityReceiver = null;
-    private ILocationListener mProximityListener = null;
-    private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
-        new HashMap<PendingIntent,ProximityAlert>();
-    private HashSet<ProximityAlert> mProximitiesEntered =
-        new HashSet<ProximityAlert>();
+    GeofenceManager mGeofenceManager;
 
     // Last known location for each provider
     private HashMap<String,Location> mLastKnownLocation =
@@ -266,13 +252,6 @@
             throw new IllegalStateException("Request for non-existent listener");
         }
 
-        public PendingIntent getPendingIntent() {
-            if (mPendingIntent != null) {
-                return mPendingIntent;
-            }
-            throw new IllegalStateException("Request for non-existent intent");
-        }
-
         public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
             if (mListener != null) {
                 try {
@@ -280,11 +259,9 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mListener.onStatusChanged(provider, status, extras);
-                        if (mListener != mProximityListener) {
-                            // call this after broadcasting so we do not increment
-                            // if we throw an exeption.
-                            incrementPendingBroadcastsLocked();
-                        }
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
                     }
                 } catch (RemoteException e) {
                     return false;
@@ -317,11 +294,9 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mListener.onLocationChanged(location);
-                        if (mListener != mProximityListener) {
-                            // call this after broadcasting so we do not increment
-                            // if we throw an exeption.
-                            incrementPendingBroadcastsLocked();
-                        }
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
                     }
                 } catch (RemoteException e) {
                     return false;
@@ -357,11 +332,9 @@
                         } else {
                             mListener.onProviderDisabled(provider);
                         }
-                        if (mListener != mProximityListener) {
-                            // call this after broadcasting so we do not increment
-                            // if we throw an exeption.
-                            incrementPendingBroadcastsLocked();
-                        }
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
                     }
                 } catch (RemoteException e) {
                     return false;
@@ -402,6 +375,7 @@
             }
         }
 
+        @Override
         public void onSendFinished(PendingIntent pendingIntent, Intent intent,
                 int resultCode, String resultData, Bundle resultExtras) {
             synchronized (this) {
@@ -424,6 +398,7 @@
         }
     }
 
+    @Override
     public void locationCallbackFinished(ILocationListener listener) {
         //Do not use getReceiver here as that will add the ILocationListener to
         //the receiver list if it is not found.  If it is not found then the
@@ -442,6 +417,7 @@
     }
 
     private final class SettingsObserver implements Observer {
+        @Override
         public void update(Observable o, Object arg) {
             synchronized (mLock) {
                 updateProvidersLocked();
@@ -588,7 +564,7 @@
     }
 
     void systemReady() {
-        // we defer starting up the service until the system is ready 
+        // we defer starting up the service until the system is ready
         Thread thread = new Thread(null, this, "LocationManagerService");
         thread.start();
     }
@@ -616,20 +592,22 @@
         // listen for settings changes
         ContentResolver resolver = mContext.getContentResolver();
         Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
-                "(" + Settings.System.NAME + "=?)",
+                "(" + NameValueTable.NAME + "=?)",
                 new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
                 null);
-        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
+        mSettings = new ContentQueryMap(settingsCursor, NameValueTable.NAME, true, mLocationHandler);
         SettingsObserver settingsObserver = new SettingsObserver();
         mSettings.addObserver(settingsObserver);
     }
 
+    @Override
     public void run()
     {
         Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
         Looper.prepare();
         mLocationHandler = new LocationWorkerHandler();
         initialize();
+        mGeofenceManager = new GeofenceManager(mContext);
         Looper.loop();
     }
 
@@ -690,6 +668,7 @@
         return true;
     }
 
+    @Override
     public List<String> getAllProviders() {
         try {
             synchronized (mLock) {
@@ -715,6 +694,7 @@
         return out;
     }
 
+    @Override
     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
         try {
             synchronized (mLock) {
@@ -782,6 +762,7 @@
     }
 
     private class LpPowerComparator implements Comparator<LocationProviderInterface> {
+        @Override
         public int compare(LocationProviderInterface l1, LocationProviderInterface l2) {
             // Smaller is better
             return (l1.getPowerRequirement() - l2.getPowerRequirement());
@@ -793,6 +774,7 @@
     }
 
     private class LpAccuracyComparator implements Comparator<LocationProviderInterface> {
+        @Override
         public int compare(LocationProviderInterface l1, LocationProviderInterface l2) {
             // Smaller is better
             return (l1.getAccuracy() - l2.getAccuracy());
@@ -815,6 +797,7 @@
                 (p.supportsSpeed() ? SPEED_SCORE : 0);
         }
 
+        @Override
         public int compare(LocationProviderInterface l1, LocationProviderInterface l2) {
             return (score(l2) - score(l1)); // Bigger is better
          }
@@ -896,6 +879,7 @@
      * @param enabledOnly if true then only a provider that is currently enabled is returned
      * @return name of the provider that best matches the requirements
      */
+    @Override
     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
         List<String> goodProviders = getProviders(criteria, enabledOnly);
         if (!goodProviders.isEmpty()) {
@@ -951,6 +935,7 @@
         return null;
     }
 
+    @Override
     public boolean providerMeetsCriteria(String provider, Criteria criteria) {
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
@@ -988,7 +973,7 @@
         }
 
         ArrayList<Receiver> deadReceivers = null;
-        
+
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
         if (records != null) {
             final int N = records.size();
@@ -1010,7 +995,7 @@
                 removeUpdatesLocked(deadReceivers.get(i));
             }
         }
-        
+
         if (enabled) {
             p.enable();
             if (listeners > 0) {
@@ -1148,14 +1133,10 @@
                 }
            }
         }
-        for (ProximityAlert alert : mProximityAlerts.values()) {
-            if (alert.mUid == uid) {
-                return true;
-            }
-        }
         return false;
     }
 
+    @Override
     public void requestLocationUpdates(String provider, Criteria criteria,
         long minTime, float minDistance, boolean singleShot, ILocationListener listener) {
         if (criteria != null) {
@@ -1181,6 +1162,20 @@
         }
     }
 
+    void validatePackageName(int uid, String packageName) {
+        if (packageName == null) {
+            throw new SecurityException("packageName cannot be null");
+        }
+        String[] packages = mPackageManager.getPackagesForUid(uid);
+        if (packages == null) {
+            throw new SecurityException("invalid UID " + uid);
+        }
+        for (String pkg : packages) {
+            if (packageName.equals(pkg)) return;
+        }
+        throw new SecurityException("invalid package name");
+    }
+
     void validatePendingIntent(PendingIntent intent) {
         if (intent.isTargetedToPackage()) {
             return;
@@ -1193,6 +1188,7 @@
         //        + intent);
     }
 
+    @Override
     public void requestLocationUpdatesPI(String provider, Criteria criteria,
             long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
         validatePendingIntent(intent);
@@ -1270,6 +1266,7 @@
         }
     }
 
+    @Override
     public void removeUpdates(ILocationListener listener) {
         try {
             synchronized (mLock) {
@@ -1284,6 +1281,7 @@
         }
     }
 
+    @Override
     public void removeUpdatesPI(PendingIntent intent) {
         try {
             synchronized (mLock) {
@@ -1370,6 +1368,7 @@
         }
     }
 
+    @Override
     public boolean addGpsStatusListener(IGpsStatusListener listener) {
         if (mGpsStatusProvider == null) {
             return false;
@@ -1388,6 +1387,7 @@
         return true;
     }
 
+    @Override
     public void removeGpsStatusListener(IGpsStatusListener listener) {
         synchronized (mLock) {
             try {
@@ -1398,6 +1398,7 @@
         }
     }
 
+    @Override
     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
         if (provider == null) {
             // throw NullPointerException to remain compatible with previous implementation
@@ -1417,11 +1418,12 @@
             if (p == null) {
                 return false;
             }
-    
+
             return p.sendExtraCommand(command, extras);
         }
     }
 
+    @Override
     public boolean sendNiResponse(int notifId, int userResponse)
     {
         if (Binder.getCallingUid() != Process.myUid()) {
@@ -1438,223 +1440,11 @@
         }
     }
 
-    class ProximityAlert {
-        final int  mUid;
-        final double mLatitude;
-        final double mLongitude;
-        final float mRadius;
-        final long mExpiration;
-        final PendingIntent mIntent;
-        final Location mLocation;
-
-        public ProximityAlert(int uid, double latitude, double longitude,
-            float radius, long expiration, PendingIntent intent) {
-            mUid = uid;
-            mLatitude = latitude;
-            mLongitude = longitude;
-            mRadius = radius;
-            mExpiration = expiration;
-            mIntent = intent;
-
-            mLocation = new Location("");
-            mLocation.setLatitude(latitude);
-            mLocation.setLongitude(longitude);
-        }
-
-        long getExpiration() {
-            return mExpiration;
-        }
-
-        PendingIntent getIntent() {
-            return mIntent;
-        }
-
-        boolean isInProximity(double latitude, double longitude, float accuracy) {
-            Location loc = new Location("");
-            loc.setLatitude(latitude);
-            loc.setLongitude(longitude);
-
-            double radius = loc.distanceTo(mLocation);
-            return radius <= Math.max(mRadius,accuracy);
-        }
-        
-        @Override
-        public String toString() {
-            return "ProximityAlert{"
-                    + Integer.toHexString(System.identityHashCode(this))
-                    + " uid " + mUid + mIntent + "}";
-        }
-        
-        void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + this);
-            pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
-            pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
-            pw.println(prefix + "mIntent=" + mIntent);
-            pw.println(prefix + "mLocation:");
-            mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
-        }
-    }
-
-    // Listener for receiving locations to trigger proximity alerts
-    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
-
-        boolean isGpsAvailable = false;
-
-        // Note: this is called with the lock held.
-        public void onLocationChanged(Location loc) {
-
-            // If Gps is available, then ignore updates from NetworkLocationProvider
-            if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) {
-                isGpsAvailable = true;
-            }
-            if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
-                return;
-            }
-
-            // Process proximity alerts
-            long now = System.currentTimeMillis();
-            double latitude = loc.getLatitude();
-            double longitude = loc.getLongitude();
-            float accuracy = loc.getAccuracy();
-            ArrayList<PendingIntent> intentsToRemove = null;
-
-            for (ProximityAlert alert : mProximityAlerts.values()) {
-                PendingIntent intent = alert.getIntent();
-                long expiration = alert.getExpiration();
-
-                if ((expiration == -1) || (now <= expiration)) {
-                    boolean entered = mProximitiesEntered.contains(alert);
-                    boolean inProximity =
-                        alert.isInProximity(latitude, longitude, accuracy);
-                    if (!entered && inProximity) {
-                        if (LOCAL_LOGV) {
-                            Slog.v(TAG, "Entered alert");
-                        }
-                        mProximitiesEntered.add(alert);
-                        Intent enteredIntent = new Intent();
-                        enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
-                        try {
-                            synchronized (this) {
-                                // synchronize to ensure incrementPendingBroadcasts()
-                                // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler,
-                                        ACCESS_FINE_LOCATION);
-                                // call this after broadcasting so we do not increment
-                                // if we throw an exeption.
-                                incrementPendingBroadcasts();
-                            }
-                        } catch (PendingIntent.CanceledException e) {
-                            if (LOCAL_LOGV) {
-                                Slog.v(TAG, "Canceled proximity alert: " + alert, e);
-                            }
-                            if (intentsToRemove == null) {
-                                intentsToRemove = new ArrayList<PendingIntent>();
-                            }
-                            intentsToRemove.add(intent);
-                        }
-                    } else if (entered && !inProximity) {
-                        if (LOCAL_LOGV) {
-                            Slog.v(TAG, "Exited alert");
-                        }
-                        mProximitiesEntered.remove(alert);
-                        Intent exitedIntent = new Intent();
-                        exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
-                        try {
-                            synchronized (this) {
-                                // synchronize to ensure incrementPendingBroadcasts()
-                                // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler,
-                                        ACCESS_FINE_LOCATION);
-                                // call this after broadcasting so we do not increment
-                                // if we throw an exeption.
-                                incrementPendingBroadcasts();
-                            }
-                        } catch (PendingIntent.CanceledException e) {
-                            if (LOCAL_LOGV) {
-                                Slog.v(TAG, "Canceled proximity alert: " + alert, e);
-                            }
-                            if (intentsToRemove == null) {
-                                intentsToRemove = new ArrayList<PendingIntent>();
-                            }
-                            intentsToRemove.add(intent);
-                        }
-                    }
-                } else {
-                    // Mark alert for expiration
-                    if (LOCAL_LOGV) {
-                        Slog.v(TAG, "Expiring proximity alert: " + alert);
-                    }
-                    if (intentsToRemove == null) {
-                        intentsToRemove = new ArrayList<PendingIntent>();
-                    }
-                    intentsToRemove.add(alert.getIntent());
-                }
-            }
-
-            // Remove expired alerts
-            if (intentsToRemove != null) {
-                for (PendingIntent i : intentsToRemove) {
-                    ProximityAlert alert = mProximityAlerts.get(i);
-                    mProximitiesEntered.remove(alert);
-                    removeProximityAlertLocked(i);
-                }
-            }
-        }
-
-        // Note: this is called with the lock held.
-        public void onProviderDisabled(String provider) {
-            if (provider.equals(LocationManager.GPS_PROVIDER)) {
-                isGpsAvailable = false;
-            }
-        }
-
-        // Note: this is called with the lock held.
-        public void onProviderEnabled(String provider) {
-            // ignore
-        }
-
-        // Note: this is called with the lock held.
-        public void onStatusChanged(String provider, int status, Bundle extras) {
-            if ((provider.equals(LocationManager.GPS_PROVIDER)) &&
-                (status != LocationProvider.AVAILABLE)) {
-                isGpsAvailable = false;
-            }
-        }
-
-        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
-                int resultCode, String resultData, Bundle resultExtras) {
-            // synchronize to ensure incrementPendingBroadcasts()
-            // is called before decrementPendingBroadcasts()
-            synchronized (this) {
-                decrementPendingBroadcasts();
-            }
-        }
-    }
-
+    @Override
     public void addProximityAlert(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent) {
+            float radius, long expiration, PendingIntent intent, String packageName) {
         validatePendingIntent(intent);
-        try {
-            synchronized (mLock) {
-                addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "addProximityAlert got exception:", e);
-        }
-    }
-
-    private void addProximityAlertLocked(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "addProximityAlert: latitude = " + latitude +
-                    ", longitude = " + longitude +
-                    ", expiration = " + expiration +
-                    ", intent = " + intent);
-        }
+        validatePackageName(Binder.getCallingUid(), packageName);
 
         // Require ability to access all providers for now
         if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
@@ -1662,59 +1452,28 @@
             throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
         }
 
-        if (expiration != -1) {
-            expiration += System.currentTimeMillis();
-        }
-        ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
-                latitude, longitude, radius, expiration, intent);
-        mProximityAlerts.put(intent, alert);
+        if (LOCAL_LOGV) Slog.v(TAG, "addProximityAlert: lat=" + latitude + ", long=" + longitude +
+                ", radius=" + radius + ", exp=" + expiration + ", intent = " + intent);
 
-        if (mProximityReceiver == null) {
-            mProximityListener = new ProximityListener();
-            mProximityReceiver = new Receiver(mProximityListener);
-
-            for (int i = mProviders.size() - 1; i >= 0; i--) {
-                LocationProviderInterface provider = mProviders.get(i);
-                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f,
-                        false, mProximityReceiver);
-            }
-        }
+        mGeofenceManager.addFence(latitude, longitude, radius, expiration, intent,
+                Binder.getCallingUid(), packageName);
     }
 
+    @Override
     public void removeProximityAlert(PendingIntent intent) {
-        try {
-            synchronized (mLock) {
-               removeProximityAlertLocked(intent);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "removeProximityAlert got exception:", e);
-        }
+        if (intent == null) throw new NullPointerException("pending intent is null");
+
+        if (LOCAL_LOGV) Slog.v(TAG, "removeProximityAlert: intent = " + intent);
+
+        mGeofenceManager.removeFence(intent);
     }
 
-    private void removeProximityAlertLocked(PendingIntent intent) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "removeProximityAlert: intent = " + intent);
-        }
-
-        mProximityAlerts.remove(intent);
-        if (mProximityAlerts.size() == 0) {
-            if (mProximityReceiver != null) {
-                removeUpdatesLocked(mProximityReceiver);
-            }
-            mProximityReceiver = null;
-            mProximityListener = null;
-        }
-     }
-
     /**
      * @return null if the provider does not exist
      * @throws SecurityException if the provider is not allowed to be
      * accessed by the caller
      */
+    @Override
     public Bundle getProviderInfo(String provider) {
         try {
             synchronized (mLock) {
@@ -1752,6 +1511,7 @@
         return b;
     }
 
+    @Override
     public boolean isProviderEnabled(String provider) {
         try {
             synchronized (mLock) {
@@ -1765,12 +1525,18 @@
         }
     }
 
+    @Override
     public void reportLocation(Location location, boolean passive) {
         if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
         }
 
+        if (!location.isComplete()) {
+            Log.w(TAG, "Dropping incomplete location: " + location);
+            return;
+        }
+
         mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
         Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
         m.arg1 = (passive ? 1 : 0);
@@ -1787,6 +1553,7 @@
         return isAllowedBySettingsLocked(provider);
     }
 
+    @Override
     public Location getLastKnownLocation(String provider) {
         if (LOCAL_LOGV) {
             Slog.v(TAG, "getLastKnownLocation: " + provider);
@@ -1826,7 +1593,8 @@
 
         // Check whether sufficient time has passed
         long minTime = record.mMinTime;
-        if (loc.getTime() - lastLoc.getTime() < minTime - MAX_PROVIDER_SCHEDULING_JITTER) {
+        long delta = (loc.getElapsedRealtimeNano() - lastLoc.getElapsedRealtimeNano()) / 1000000L;
+        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER) {
             return false;
         }
 
@@ -1869,7 +1637,7 @@
         int status = p.getStatus(extras);
 
         ArrayList<Receiver> deadReceivers = null;
-        
+
         // Broadcast location or status to all listeners
         final int N = records.size();
         for (int i=0; i<N; i++) {
@@ -1912,7 +1680,7 @@
                 }
             }
         }
-        
+
         if (deadReceivers != null) {
             for (int i=deadReceivers.size()-1; i>=0; i--) {
                 removeUpdatesLocked(deadReceivers.get(i));
@@ -2024,31 +1792,6 @@
                                     }
                                 }
                             }
-                            ArrayList<ProximityAlert> removedAlerts = null;
-                            for (ProximityAlert i : mProximityAlerts.values()) {
-                                if (i.mUid == uid) {
-                                    if (queryRestart) {
-                                        setResultCode(Activity.RESULT_OK);
-                                        return;
-                                    }
-                                    if (removedAlerts == null) {
-                                        removedAlerts = new ArrayList<ProximityAlert>();
-                                    }
-                                    if (!removedAlerts.contains(i)) {
-                                        removedAlerts.add(i);
-                                    }
-                                }
-                            }
-                            if (removedRecs != null) {
-                                for (int i=removedRecs.size()-1; i>=0; i--) {
-                                    removeUpdatesLocked(removedRecs.get(i));
-                                }
-                            }
-                            if (removedAlerts != null) {
-                                for (int i=removedAlerts.size()-1; i>=0; i--) {
-                                    removeProximityAlertLocked(removedAlerts.get(i).mIntent);
-                                }
-                            }
                         }
                     }
                 }
@@ -2089,6 +1832,10 @@
             // Called by main thread; divert work to LocationWorker.
             Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget();
         }
+        @Override
+        public void onPackageDisappeared(String packageName, int uid) {
+            mGeofenceManager.removeFence(packageName);
+        }
     };
 
     // Wake locks
@@ -2130,10 +1877,12 @@
 
     // Geocoder
 
+    @Override
     public boolean geocoderIsPresent() {
         return mGeocodeProvider != null;
     }
 
+    @Override
     public String getFromLocation(double latitude, double longitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
         if (mGeocodeProvider != null) {
@@ -2144,6 +1893,7 @@
     }
 
 
+    @Override
     public String getFromLocationName(String locationName,
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
@@ -2169,9 +1919,10 @@
         if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
             PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
-        }            
+        }
     }
 
+    @Override
     public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
         boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
@@ -2207,6 +1958,7 @@
         Binder.restoreCallingIdentity(identity);
     }
 
+    @Override
     public void removeTestProvider(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2231,6 +1983,7 @@
         }
     }
 
+    @Override
     public void setTestProviderLocation(String provider, Location loc) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2245,6 +1998,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderLocation(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2256,6 +2010,7 @@
         }
     }
 
+    @Override
     public void setTestProviderEnabled(String provider, boolean enabled) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2278,6 +2033,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderEnabled(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2293,6 +2049,7 @@
         }
     }
 
+    @Override
     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2304,6 +2061,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderStatus(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2320,7 +2078,8 @@
             Slog.d(TAG, log);
         }
     }
-    
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -2329,7 +2088,7 @@
                     + ", uid=" + Binder.getCallingUid());
             return;
         }
-        
+
         synchronized (mLock) {
             pw.println("Current Location Manager state:");
             pw.println("  sProvidersLoaded=" + sProvidersLoaded);
@@ -2361,36 +2120,20 @@
                 pw.println("    " + i.getKey() + ":");
                 i.getValue().dump(new PrintWriterPrinter(pw), "      ");
             }
-            if (mProximityAlerts.size() > 0) {
-                pw.println("  Proximity Alerts:");
-                for (Map.Entry<PendingIntent, ProximityAlert> i
-                        : mProximityAlerts.entrySet()) {
-                    pw.println("    " + i.getKey() + ":");
-                    i.getValue().dump(pw, "      ");
-                }
-            }
-            if (mProximitiesEntered.size() > 0) {
-                pw.println("  Proximities Entered:");
-                for (ProximityAlert i : mProximitiesEntered) {
-                    pw.println("    " + i + ":");
-                    i.dump(pw, "      ");
-                }
-            }
-            pw.println("  mProximityReceiver=" + mProximityReceiver);
-            pw.println("  mProximityListener=" + mProximityListener);
+            mGeofenceManager.dump(pw);
             if (mEnabledProviders.size() > 0) {
                 pw.println("  Enabled Providers:");
                 for (String i : mEnabledProviders) {
                     pw.println("    " + i);
                 }
-                
+
             }
             if (mDisabledProviders.size() > 0) {
                 pw.println("  Disabled Providers:");
                 for (String i : mDisabledProviders) {
                     pw.println("    " + i);
                 }
-                
+
             }
             if (mMockProviders.size() > 0) {
                 pw.println("  Mock Providers:");
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index f71125a..92af9a9 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -35,6 +35,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
 import java.util.LinkedList;
 
 /**
@@ -482,102 +485,108 @@
 
     private static class ResponseQueue {
 
-        private static class Response {
+        private static class PendingCmd {
             public int cmdNum;
-            public LinkedList<NativeDaemonEvent> responses = new LinkedList<NativeDaemonEvent>();
+            public BlockingQueue<NativeDaemonEvent> responses =
+                    new ArrayBlockingQueue<NativeDaemonEvent>(10);
             public String request;
-            public Response(int c, String r) {cmdNum = c; request = r;}
+
+            // The availableResponseCount member is used to track when we can remove this
+            // instance from the ResponseQueue.
+            // This is used under the protection of a sync of the mPendingCmds object.
+            // A positive value means we've had more writers retreive this object while
+            // a negative value means we've had more readers.  When we've had an equal number
+            // (it goes to zero) we can remove this object from the mPendingCmds list.
+            // Note that we may have more responses for this command (and more readers
+            // coming), but that would result in a new PendingCmd instance being created
+            // and added with the same cmdNum.
+            // Also note that when this goes to zero it just means a parity of readers and
+            // writers have retrieved this object - not that they are done using it.  The
+            // responses queue may well have more responses yet to be read or may get more
+            // responses added to it.  But all those readers/writers have retreived and
+            // hold references to this instance already so it can be removed from
+            // mPendingCmds queue.
+            public int availableResponseCount;
+            public PendingCmd(int c, String r) {cmdNum = c; request = r;}
         }
 
-        private final LinkedList<Response> mResponses;
+        private final LinkedList<PendingCmd> mPendingCmds;
         private int mMaxCount;
 
         ResponseQueue(int maxCount) {
-            mResponses = new LinkedList<Response>();
+            mPendingCmds = new LinkedList<PendingCmd>();
             mMaxCount = maxCount;
         }
 
         public void add(int cmdNum, NativeDaemonEvent response) {
-            Response found = null;
-            synchronized (mResponses) {
-                for (Response r : mResponses) {
-                    if (r.cmdNum == cmdNum) {
-                        found = r;
+            PendingCmd found = null;
+            synchronized (mPendingCmds) {
+                for (PendingCmd pendingCmd : mPendingCmds) {
+                    if (pendingCmd.cmdNum == cmdNum) {
+                        found = pendingCmd;
                         break;
                     }
                 }
                 if (found == null) {
                     // didn't find it - make sure our queue isn't too big before adding
-                    // another..
-                    while (mResponses.size() >= mMaxCount) {
+                    while (mPendingCmds.size() >= mMaxCount) {
                         Slog.e("NativeDaemonConnector.ResponseQueue",
-                                "more buffered than allowed: " + mResponses.size() +
+                                "more buffered than allowed: " + mPendingCmds.size() +
                                 " >= " + mMaxCount);
                         // let any waiter timeout waiting for this
-                        Response r = mResponses.remove();
+                        PendingCmd pendingCmd = mPendingCmds.remove();
                         Slog.e("NativeDaemonConnector.ResponseQueue",
-                                "Removing request: " + r.request + " (" + r.cmdNum + ")");
+                                "Removing request: " + pendingCmd.request + " (" +
+                                pendingCmd.cmdNum + ")");
                     }
-                    found = new Response(cmdNum, null);
-                    mResponses.add(found);
+                    found = new PendingCmd(cmdNum, null);
+                    mPendingCmds.add(found);
                 }
-                found.responses.add(response);
+                found.availableResponseCount++;
+                // if a matching remove call has already retrieved this we can remove this
+                // instance from our list
+                if (found.availableResponseCount == 0) mPendingCmds.remove(found);
             }
-            synchronized (found) {
-                found.notify();
-            }
+            try {
+                found.responses.put(response);
+            } catch (InterruptedException e) { }
         }
 
         // note that the timeout does not count time in deep sleep.  If you don't want
         // the device to sleep, hold a wakelock
         public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
-            long endTime = SystemClock.uptimeMillis() + timeoutMs;
-            long nowTime;
-            Response found = null;
-            while (true) {
-                synchronized (mResponses) {
-                    for (Response response : mResponses) {
-                        if (response.cmdNum == cmdNum) {
-                            found = response;
-                            // how many response fragments are left
-                            switch (response.responses.size()) {
-                            case 0:  // haven't got any - must wait
-                                break;
-                            case 1:  // last one - remove this from the master list
-                                mResponses.remove(response); // fall through
-                            default: // take one and move on
-                                response.request = origCmd;
-                                return response.responses.remove();
-                            }
-                        }
-                    }
-                    nowTime = SystemClock.uptimeMillis();
-                    if (endTime <= nowTime) {
-                        Slog.e("NativeDaemonConnector.ResponseQueue",
-                                "Timeout waiting for response");
-                        return null;
-                    }
-                    /* pre-allocate so we have something unique to wait on */
-                    if (found == null) {
-                        found = new Response(cmdNum, origCmd);
-                        mResponses.add(found);
+            PendingCmd found = null;
+            synchronized (mPendingCmds) {
+                for (PendingCmd pendingCmd : mPendingCmds) {
+                    if (pendingCmd.cmdNum == cmdNum) {
+                        found = pendingCmd;
+                        break;
                     }
                 }
-                try {
-                    synchronized (found) {
-                        found.wait(endTime - nowTime);
-                    }
-                } catch (InterruptedException e) {
-                    // loop around to check if we're done or if it's time to stop waiting
+                if (found == null) {
+                    found = new PendingCmd(cmdNum, origCmd);
+                    mPendingCmds.add(found);
                 }
+                found.availableResponseCount--;
+                // if a matching add call has already retrieved this we can remove this
+                // instance from our list
+                if (found.availableResponseCount == 0) mPendingCmds.remove(found);
             }
+            NativeDaemonEvent result = null;
+            try {
+                result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {}
+            if (result == null) {
+                Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
+            }
+            return result;
         }
 
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             pw.println("Pending requests:");
-            synchronized (mResponses) {
-                for (Response response : mResponses) {
-                    pw.println("  Cmd " + response.cmdNum + " - " + response.request);
+            synchronized (mPendingCmds) {
+                for (PendingCmd pendingCmd : mPendingCmds) {
+                    pw.println("  Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.request);
                 }
             }
         }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 11644e3..c3f3a5d 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -78,6 +78,7 @@
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
 import java.util.concurrent.CountDownLatch;
+import android.bluetooth.BluetoothTetheringDataTracker;
 
 /**
  * @hide
@@ -121,6 +122,7 @@
 
         public static final int InterfaceChange           = 600;
         public static final int BandwidthControl          = 601;
+        public static final int InterfaceClassActivity    = 613;
     }
 
     /**
@@ -278,6 +280,20 @@
     }
 
     /**
+     * Notify our observers of a change in the data activity state of the interface
+     */
+    private void notifyInterfaceClassActivity(String label, boolean active) {
+        final int length = mObservers.beginBroadcast();
+        for (int i = 0; i < length; i++) {
+            try {
+                mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(label, active);
+            } catch (RemoteException e) {
+            }
+        }
+        mObservers.finishBroadcast();
+    }
+
+    /**
      * Prepare native daemon once connected, enabling modules and pushing any
      * existing in-memory rules.
      */
@@ -403,6 +419,19 @@
                     throw new IllegalStateException(
                             String.format("Invalid event from daemon (%s)", raw));
                     // break;
+            case NetdResponseCode.InterfaceClassActivity:
+                    /*
+                     * An network interface class state changed (active/idle)
+                     * Format: "NNN IfaceClass <active/idle> <label>"
+                     */
+                    if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
+                        throw new IllegalStateException(
+                                String.format("Invalid event from daemon (%s)", raw));
+                    }
+                    boolean isActive = cooked[2].equals("active");
+                    notifyInterfaceClassActivity(cooked[3], isActive);
+                    return true;
+                    // break;
             default: break;
             }
             return false;
@@ -780,6 +809,36 @@
         return event.getMessage().endsWith("started");
     }
 
+    // TODO(BT) Remove
+    public void startReverseTethering(String iface)
+             throws IllegalStateException {
+        if (DBG) Slog.d(TAG, "startReverseTethering in");
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        // cmd is "tether start first_start first_stop second_start second_stop ..."
+        // an odd number of addrs will fail
+        String cmd = "tether start-reverse";
+        cmd += " " + iface;
+        if (DBG) Slog.d(TAG, "startReverseTethering cmd: " + cmd);
+        try {
+            mConnector.doCommand(cmd);
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException("Unable to communicate to native daemon");
+        }
+        BluetoothTetheringDataTracker.getInstance().startReverseTether(iface);
+
+    }
+
+    // TODO(BT) Remove
+    public void stopReverseTethering() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        try {
+            mConnector.doCommand("tether stop-reverse");
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException("Unable to communicate to native daemon to stop tether");
+        }
+        BluetoothTetheringDataTracker.getInstance().stopReverseTether();
+    }
+
     @Override
     public void tetherInterface(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -923,14 +982,14 @@
 
     @Override
     public void startAccessPoint(
-            WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
+            WifiConfiguration wifiConfig, String wlanIface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
             wifiFirmwareReload(wlanIface, "AP");
             if (wifiConfig == null) {
-                mConnector.execute("softap", "set", wlanIface, softapIface);
+                mConnector.execute("softap", "set", wlanIface);
             } else {
-                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
+                mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                         getSecurityType(wifiConfig), wifiConfig.preSharedKey);
             }
             mConnector.execute("softap", "startap");
@@ -966,7 +1025,6 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
             mConnector.execute("softap", "stopap");
-            mConnector.execute("softap", "stop", wlanIface);
             wifiFirmwareReload(wlanIface, "STA");
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
@@ -974,13 +1032,13 @@
     }
 
     @Override
-    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
+    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
             if (wifiConfig == null) {
-                mConnector.execute("softap", "set", wlanIface, softapIface);
+                mConnector.execute("softap", "set", wlanIface);
             } else {
-                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
+                mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                         getSecurityType(wifiConfig), wifiConfig.preSharedKey);
             }
         } catch (NativeDaemonConnectorException e) {
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
index d85abe6..a4341b7 100644
--- a/services/java/com/android/server/ShutdownActivity.java
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -17,13 +17,12 @@
 package com.android.server;
 
 import android.app.Activity;
-import android.content.BroadcastReceiver;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Slog;
 
-import com.android.server.pm.ShutdownThread;
+import com.android.server.power.ShutdownThread;
 
 public class ShutdownActivity extends Activity {
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f300d74..2185456 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -36,8 +36,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import android.server.BluetoothA2dpService;
-import android.server.BluetoothService;
 import android.server.search.SearchManagerService;
 import android.service.dreams.DreamManagerService;
 import android.util.DisplayMetrics;
@@ -55,7 +53,8 @@
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
 import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.ShutdownThread;
+import com.android.server.power.PowerManagerService;
+import com.android.server.power.ShutdownThread;
 import com.android.server.usb.UsbService;
 import com.android.server.wm.WindowManagerService;
 
@@ -129,8 +128,7 @@
         IPackageManager pm = null;
         Context context = null;
         WindowManagerService wm = null;
-        BluetoothService bluetooth = null;
-        BluetoothA2dpService bluetoothA2dp = null;
+        BluetoothManagerService bluetooth = null;
         DockObserver dock = null;
         UsbService usb = null;
         SerialService serial = null;
@@ -244,23 +242,9 @@
             } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
             } else {
-                Slog.i(TAG, "Bluetooth Service");
-                bluetooth = new BluetoothService(context);
-                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);
-                bluetooth.initAfterRegistration();
-
-                if (!"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
-                    bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
-                    ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
-                                              bluetoothA2dp);
-                    bluetooth.initAfterA2dpRegistration();
-                }
-
-                int bluetoothOn = Settings.Secure.getInt(mContentResolver,
-                    Settings.Secure.BLUETOOTH_ON, 0);
-                if (bluetoothOn != 0) {
-                    bluetooth.enable();
-                }
+                Slog.i(TAG, "Bluetooth Manager Service");
+                bluetooth = new BluetoothManagerService(context);
+                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
             }
 
         } catch (RuntimeException e) {
@@ -747,7 +731,6 @@
         final StatusBarManagerService statusBarF = statusBar;
         final DreamManagerService dreamyF = dreamy;
         final InputManagerService inputManagerF = inputManager;
-        final BluetoothService bluetoothF = bluetooth;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -860,7 +843,8 @@
                     reportWtf("making DreamManagerService ready", e);
                 }
                 try {
-                    if (inputManagerF != null) inputManagerF.systemReady(bluetoothF);
+                    // TODO(BT) Pass parameter to input manager
+                    if (inputManagerF != null) inputManagerF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making InputManagerService ready", e);
                 }
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index f35a5af..98e6dc0 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -195,6 +195,7 @@
 
         public void interfaceRemoved(String iface) {}
         public void limitReached(String limitName, String iface) {}
+        public void interfaceClassDataActivityChanged(String label, boolean active) {}
     }
 
 
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index d1f92a7..5299b71 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -308,7 +308,7 @@
             /* if new location is older than the current one, the devices hasn't
              * moved.
              */
-            if (location.getTime() < mLocation.getTime()) {
+            if (location.getElapsedRealtimeNano() < mLocation.getElapsedRealtimeNano()) {
                 return false;
             }
 
@@ -764,7 +764,8 @@
                         mLocationManager.getLastKnownLocation(providers.next());
                 // pick the most recent location
                 if (location == null || (lastKnownLocation != null &&
-                        location.getTime() < lastKnownLocation.getTime())) {
+                        location.getElapsedRealtimeNano() <
+                        lastKnownLocation.getElapsedRealtimeNano())) {
                     location = lastKnownLocation;
                 }
             }
@@ -781,6 +782,7 @@
                 location.setLatitude(0);
                 location.setAccuracy(417000.0f);
                 location.setTime(System.currentTimeMillis());
+                location.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
             }
             synchronized (mLock) {
                 mLocation = location;
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index c239382..c5b4a07 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import com.android.server.am.ActivityManagerService;
+import com.android.server.power.PowerManagerService;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 1f03d17..53fb60b 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -58,6 +58,7 @@
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Slog;
 
 import java.util.ArrayList;
@@ -110,10 +111,6 @@
     private int mScanLocksAcquired;
     private int mScanLocksReleased;
 
-    /* A mapping from UID to scan count */
-    private HashMap<Integer, Integer> mScanCount =
-            new HashMap<Integer, Integer>();
-
     private final List<Multicaster> mMulticasters =
             new ArrayList<Multicaster>();
     private int mMulticastEnabled;
@@ -161,6 +158,10 @@
     /* Tracks whether wifi is enabled from WifiStateMachine's perspective */
     private boolean mWifiEnabled;
 
+    /* The work source (UID) that triggered the current WIFI scan, synchronized
+     * on this */
+    private WorkSource mScanWorkSource;
+
     private boolean mIsReceiverRegistered = false;
 
 
@@ -413,6 +414,7 @@
                             }
                         } else if (intent.getAction().equals(
                                 WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                            noteScanEnd();
                             checkAndSetNotification();
                         }
                     }
@@ -430,6 +432,44 @@
         mNotificationEnabledSettingObserver.register();
     }
 
+    /** Tell battery stats about a new WIFI scan */
+    private void noteScanStart() {
+        WorkSource scanWorkSource = null;
+        synchronized (WifiService.this) {
+            if (mScanWorkSource != null) {
+                // Scan already in progress, don't add this one to battery stats
+                return;
+            }
+            scanWorkSource = new WorkSource(Binder.getCallingUid());
+            mScanWorkSource = scanWorkSource;
+        }
+
+        long id = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteWifiScanStartedFromSource(scanWorkSource);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } finally {
+            Binder.restoreCallingIdentity(id);
+        }
+    }
+
+    /** Tell battery stats that the current WIFI scan has completed */
+    private void noteScanEnd() {
+        WorkSource scanWorkSource = null;
+        synchronized (WifiService.this) {
+            scanWorkSource = mScanWorkSource;
+            mScanWorkSource = null;
+        }
+        if (scanWorkSource != null) {
+            try {
+                mBatteryStats.noteWifiScanStoppedFromSource(scanWorkSource);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
+            }
+        }
+    }
+
     /**
      * Check if Wi-Fi needs to be enabled and start
      * if needed
@@ -541,16 +581,8 @@
      */
     public void startScan(boolean forceActive) {
         enforceChangePermission();
-
-        int uid = Binder.getCallingUid();
-        int count = 0;
-        synchronized (mScanCount) {
-            if (mScanCount.containsKey(uid)) {
-                count = mScanCount.get(uid);
-            }
-            mScanCount.put(uid, ++count);
-        }
         mWifiStateMachine.startScan(forceActive);
+        noteScanStart();
     }
 
     private void enforceAccessPermission() {
@@ -1011,12 +1043,6 @@
                     mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
                 }
 
-                //Start scan stats tracking when device unplugged
-                if (pluggedType == 0) {
-                    synchronized (mScanCount) {
-                        mScanCount.clear();
-                    }
-                }
                 mPluggedType = pluggedType;
             } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
@@ -1207,13 +1233,6 @@
         pw.println("Locks held:");
         mLocks.dump(pw);
 
-        pw.println("Scan count since last plugged in");
-        synchronized (mScanCount) {
-            for(int sc : mScanCount.keySet()) {
-                pw.println("UID: " + sc + " Scan count: " + mScanCount.get(sc));
-            }
-        }
-
         pw.println();
         pw.println("WifiWatchdogStateMachine dump");
         mWifiWatchdogStateMachine.dump(pw);
@@ -1333,10 +1352,8 @@
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
-                mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
-                break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
-                mBatteryStats.noteScanWifiLockAcquiredFromSource(wifiLock.mWorkSource);
+                mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
                 break;
         }
     }
@@ -1345,10 +1362,8 @@
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
-                mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
-                break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
-                mBatteryStats.noteScanWifiLockReleasedFromSource(wifiLock.mWorkSource);
+                mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
                 break;
         }
     }
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 8fa6722..fc774d4 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -16,13 +16,12 @@
 
 package com.android.server.accessibility;
 
-import com.android.server.input.InputFilter;
-
 import android.content.Context;
 import android.os.PowerManager;
 import android.util.Slog;
 import android.view.InputDevice;
 import android.view.InputEvent;
+import android.view.InputFilter;
 import android.view.MotionEvent;
 import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e42ec84..857334e 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -58,6 +58,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.IWindow;
+import android.view.IWindowManager;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -74,7 +75,6 @@
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.server.wm.WindowManagerService;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -157,7 +157,7 @@
 
     private boolean mIsTouchExplorationEnabled;
 
-    private final WindowManagerService mWindowManagerService;
+    private final IWindowManager mWindowManager;
 
     private final SecurityPolicy mSecurityPolicy;
 
@@ -181,8 +181,7 @@
     public AccessibilityManagerService(Context context) {
         mContext = context;
         mPackageManager = mContext.getPackageManager();
-        mWindowManagerService = (WindowManagerService) ServiceManager.getService(
-                Context.WINDOW_SERVICE);
+        mWindowManager = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
         mSecurityPolicy = new SecurityPolicy();
         mMainHandler = new MainHanler();
         registerPackageChangeAndBootCompletedBroadcastReceiver();
@@ -358,8 +357,7 @@
                         // We will update when the automation service dies.
                         if (mUiAutomationService == null) {
                             populateTouchExplorationGrantedAccessibilityServicesLocked();
-                            unbindAllServicesLocked();
-                            manageServicesLocked();
+                            handleTouchExplorationGrantedAccessibilityServicesChangedLocked();
                         }
                     }
                 }
@@ -584,15 +582,21 @@
      *
      * @param outBounds The output to which to write the bounds.
      */
-    void getActiveWindowBounds(Rect outBounds) {
+    boolean getActiveWindowBounds(Rect outBounds) {
         synchronized (mLock) {
             final int windowId = mSecurityPolicy.mActiveWindowId;
             IBinder token = mWindowIdToWindowTokenMap.get(windowId);
-            mWindowManagerService.getWindowFrame(token, outBounds);
+            try {
+                mWindowManager.getWindowFrame(token, outBounds);
+                return true;
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return false;
         }
     }
 
-    int getActiveWindowId() {
+    public int getActiveWindowId() {
         return mSecurityPolicy.mActiveWindowId;
     }
 
@@ -624,7 +628,7 @@
         //       enabled accessibility services.
         for (int i = mServices.size() - 1; i >= 0; i--) {
             Service service = mServices.get(i);
-            if (service.mReqeustTouchExplorationMode && service.mIsDefault == isDefault) {
+            if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
                 service.notifyGesture(gestureId);
                 return true;
             }
@@ -967,13 +971,21 @@
                 if (mInputFilter == null) {
                     mInputFilter = new AccessibilityInputFilter(mContext, this);
                 }
-                mWindowManagerService.setInputFilter(mInputFilter);
+                try {
+                    mWindowManager.setInputFilter(mInputFilter);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
             }
             return;
         }
         if (mHasInputFilter) {
             mHasInputFilter = false;
-            mWindowManagerService.setInputFilter(null);
+            try {
+                mWindowManager.setInputFilter(null);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
         }
     }
 
@@ -1000,6 +1012,22 @@
                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
     }
 
+    private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked() {
+        final int serviceCount = mServices.size();
+        for (int i = 0; i < serviceCount; i++) {
+            Service service = mServices.get(i);
+            if (service.mRequestTouchExplorationMode
+                    && mTouchExplorationGrantedServices.contains(service.mComponentName)) {
+                tryEnableTouchExplorationLocked(service);
+                return;
+            }
+        }
+        if (mIsTouchExplorationEnabled) {
+            mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0,
+                    0).sendToTarget();
+        }
+    }
+
     private void tryEnableTouchExplorationLocked(final Service service) {
         if (!mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
             final boolean canToggleTouchExploration = mTouchExplorationGrantedServices.contains(
@@ -1163,8 +1191,6 @@
 
         boolean mCanRetrieveScreenContent;
 
-        boolean mReqeustTouchExplorationMode;
-
         boolean mIsAutomation;
 
         final Rect mTempBounds = new Rect();
@@ -1204,7 +1230,7 @@
             mIsAutomation = isAutomation;
             if (!isAutomation) {
                 mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent();
-                mReqeustTouchExplorationMode =
+                mRequestTouchExplorationMode =
                     (accessibilityServiceInfo.flags
                             & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
                 mIntent = new Intent().setComponent(mComponentName);
@@ -1334,8 +1360,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1348,10 +1372,6 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
@@ -1359,8 +1379,8 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByViewId(accessibilityNodeId, viewId,
-                        windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                        interrogatingTid);
+                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -1368,7 +1388,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1377,8 +1397,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1392,19 +1410,16 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, windowLeft,
-                        windowTop, interactionId, callback, flags, interrogatingPid,
+                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
+                        interactionId, callback, flags, interrogatingPid,
                         interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -1412,7 +1427,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1421,8 +1436,6 @@
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 long interrogatingTid) throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1436,10 +1449,6 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int allFlags = flags | ((mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0);
@@ -1447,8 +1456,8 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
-                        windowLeft, windowTop, interactionId, callback, allFlags, interrogatingPid,
-                        interrogatingTid);
+                        interactionId, callback, allFlags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -1456,7 +1465,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1465,8 +1474,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1480,18 +1487,15 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.findFocus(accessibilityNodeId, focusType, windowLeft, windowTop,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
+                        flags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
@@ -1499,7 +1503,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1508,8 +1512,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1523,18 +1525,15 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.focusSearch(accessibilityNodeId, direction, windowLeft, windowTop,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
+                        flags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
@@ -1542,7 +1541,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1820,7 +1819,12 @@
 
         private float getCompatibilityScale(int windowId) {
             IBinder windowToken = mWindowIdToWindowTokenMap.get(windowId);
-            return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+            try {
+                return mWindowManager.getWindowCompatibilityScale(windowToken);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return 1.0f;
         }
     }
 
@@ -1939,18 +1943,25 @@
         }
 
         private int getFocusedWindowId() {
-            // We call this only on window focus change or after touch
-            // exploration gesture end and the shown windows are not that
-            // many, so the linear look up is just fine.
-            IBinder token = mWindowManagerService.getFocusedWindowClientToken();
-            if (token != null) {
-                SparseArray<IBinder> windows = mWindowIdToWindowTokenMap;
-                final int windowCount = windows.size();
-                for (int i = 0; i < windowCount; i++) {
-                    if (windows.valueAt(i) == token) {
-                        return windows.keyAt(i);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                // We call this only on window focus change or after touch
+                // exploration gesture end and the shown windows are not that
+                // many, so the linear look up is just fine.
+                IBinder token = mWindowManager.getFocusedWindowToken();
+                if (token != null) {
+                    SparseArray<IBinder> windows = mWindowIdToWindowTokenMap;
+                    final int windowCount = windows.size();
+                    for (int i = 0; i < windowCount; i++) {
+                        if (windows.valueAt(i) == token) {
+                            return windows.keyAt(i);
+                        }
                     }
                 }
+            } catch (RemoteException re) {
+                /* ignore */
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
             return -1;
         }
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 48c6b2a..ba9f2cd 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
+import android.view.InputFilter;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
@@ -37,7 +38,6 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.R;
-import com.android.server.input.InputFilter;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 60085f4..db24c9c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7208,7 +7208,7 @@
         lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
         lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
         lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
-        lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+        lp.gravity = Gravity.BOTTOM | Gravity.START;
         lp.format = v.getBackground().getOpacity();
         lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -12931,7 +12931,8 @@
          * processes) from sending protected broadcasts.
          */
         if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
-                || callingUid == Process.SHELL_UID || callingUid == 0) {
+            || callingUid == Process.SHELL_UID || callingUid == Process.BLUETOOTH_UID ||
+            callingUid == 0) {
             // Always okay.
         } else if (callerApp == null || !callerApp.persistent) {
             try {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 8f797ec..ab20208 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -346,18 +346,18 @@
             mStats.noteFullWifiLockReleasedLocked(uid);
         }
     }
-    
-    public void noteScanWifiLockAcquired(int uid) {
+
+    public void noteWifiScanStarted(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockAcquiredLocked(uid);
+            mStats.noteWifiScanStartedLocked(uid);
         }
     }
-    
-    public void noteScanWifiLockReleased(int uid) {
+
+    public void noteWifiScanStopped(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockReleasedLocked(uid);
+            mStats.noteWifiScanStoppedLocked(uid);
         }
     }
 
@@ -389,17 +389,17 @@
         }
     }
 
-    public void noteScanWifiLockAcquiredFromSource(WorkSource ws) {
+    public void noteWifiScanStartedFromSource(WorkSource ws) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockAcquiredFromSourceLocked(ws);
+            mStats.noteWifiScanStartedFromSourceLocked(ws);
         }
     }
 
-    public void noteScanWifiLockReleasedFromSource(WorkSource ws) {
+    public void noteWifiScanStoppedFromSource(WorkSource ws) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockReleasedFromSourceLocked(ws);
+            mStats.noteWifiScanStoppedFromSourceLocked(ws);
         }
     }
 
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 682ecf8..e4f1f7a 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -319,6 +319,8 @@
 
     public void limitReached(String limitName, String iface) {}
 
+    public void interfaceClassDataActivityChanged(String label, boolean active) {}
+
     public int tether(String iface) {
         if (DBG) Log.d(TAG, "Tethering " + iface);
         TetherInterfaceSM sm = null;
@@ -501,8 +503,13 @@
                     mUsbTetherRequested = false;
                 }
             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
-                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+                NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
+                        ConnectivityManager.EXTRA_NETWORK_INFO);
+                if (networkInfo != null &&
+                        networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
+                    if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
+                    mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+                }
             }
         }
     }
@@ -1135,7 +1142,7 @@
         private State mStopTetheringErrorState;
         private State mSetDnsForwardersErrorState;
 
-        private ArrayList mNotifyList;
+        private ArrayList<TetherInterfaceSM> mNotifyList;
 
         private int mCurrentConnectionSequence;
         private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
@@ -1165,7 +1172,7 @@
             mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
             addState(mSetDnsForwardersErrorState);
 
-            mNotifyList = new ArrayList();
+            mNotifyList = new ArrayList<TetherInterfaceSM>();
             setInitialState(mInitialState);
         }
 
@@ -1362,8 +1369,7 @@
             protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
                 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
                 mUpstreamIfaceName = ifaceName;
-                for (Object o : mNotifyList) {
-                    TetherInterfaceSM sm = (TetherInterfaceSM)o;
+                for (TetherInterfaceSM sm : mNotifyList) {
                     sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
                             ifaceName);
                 }
@@ -1381,13 +1387,13 @@
                 switch (message.what) {
                     case CMD_TETHER_MODE_REQUESTED:
                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
-                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who.toString());
+                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
                         mNotifyList.add(who);
                         transitionTo(mTetherModeAliveState);
                         break;
                     case CMD_TETHER_MODE_UNREQUESTED:
                         who = (TetherInterfaceSM)message.obj;
-                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who.toString());
+                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                         int index = mNotifyList.indexOf(who);
                         if (index != -1) {
                             mNotifyList.remove(who);
@@ -1424,18 +1430,29 @@
                 switch (message.what) {
                     case CMD_TETHER_MODE_REQUESTED:
                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
+                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
                         mNotifyList.add(who);
                         who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
                                 mUpstreamIfaceName);
                         break;
                     case CMD_TETHER_MODE_UNREQUESTED:
                         who = (TetherInterfaceSM)message.obj;
+                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                         int index = mNotifyList.indexOf(who);
                         if (index != -1) {
+                            if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
                             mNotifyList.remove(index);
                             if (mNotifyList.isEmpty()) {
                                 turnOffMasterTetherSettings(); // transitions appropriately
+                            } else {
+                                if (DBG) {
+                                    Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
+                                            " live requests:");
+                                    for (Object o : mNotifyList) Log.d(TAG, "  " + o);
+                                }
                             }
+                        } else {
+                           Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
                         }
                         break;
                     case CMD_UPSTREAM_CHANGED:
@@ -1562,7 +1579,7 @@
             pw.println();
             pw.println("Tether state:");
             for (Object o : mIfaces.values()) {
-                pw.println(" "+o.toString());
+                pw.println(" " + o);
             }
         }
         pw.println();
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 4b82037..b12d597 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -291,6 +291,9 @@
     public void limitReached(String limit, String interfaze) {
     }
 
+    public void interfaceClassDataActivityChanged(String label, boolean active) {
+    }
+
     private void enforceControlPermission() {
         // System user is allowed to control VPN.
         if (Binder.getCallingUid() == Process.SYSTEM_UID) {
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index bdd0aa4..21100e2 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -42,8 +42,8 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
-import android.hardware.input.IInputManager;
 import android.hardware.input.IInputDevicesChangedListener;
+import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
 import android.hardware.input.KeyboardLayout;
 import android.os.Binder;
@@ -57,11 +57,12 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.server.BluetoothService;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
+import android.view.IInputFilter;
+import android.view.IInputFilterHost;
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputEvent;
@@ -108,7 +109,6 @@
     private final Callbacks mCallbacks;
     private final InputManagerHandler mHandler;
     private boolean mSystemReady;
-    private BluetoothService mBluetoothService;
     private NotificationManager mNotificationManager;
 
     // Persistent data store.  Must be locked each time during use.
@@ -137,7 +137,7 @@
 
     // State for the currently installed input filter.
     final Object mInputFilterLock = new Object();
-    InputFilter mInputFilter; // guarded by mInputFilterLock
+    IInputFilter mInputFilter; // guarded by mInputFilterLock
     InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
 
     private static native int nativeInit(InputManagerService service,
@@ -236,11 +236,11 @@
         updateShowTouchesFromSettings();
     }
 
-    public void systemReady(BluetoothService bluetoothService) {
+    // TODO(BT) Pass in paramter for bluetooth system
+    public void systemReady() {
         if (DEBUG) {
             Slog.d(TAG, "System ready.");
         }
-        mBluetoothService = bluetoothService;
         mNotificationManager = (NotificationManager)mContext.getSystemService(
                 Context.NOTIFICATION_SERVICE);
         mSystemReady = true;
@@ -425,9 +425,9 @@
      *
      * @param filter The input filter, or null to remove the current filter.
      */
-    public void setInputFilter(InputFilter filter) {
+    public void setInputFilter(IInputFilter filter) {
         synchronized (mInputFilterLock) {
-            final InputFilter oldFilter = mInputFilter;
+            final IInputFilter oldFilter = mInputFilter;
             if (oldFilter == filter) {
                 return; // nothing to do
             }
@@ -436,13 +436,21 @@
                 mInputFilter = null;
                 mInputFilterHost.disconnectLocked();
                 mInputFilterHost = null;
-                oldFilter.uninstall();
+                try {
+                    oldFilter.uninstall();
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
             }
 
             if (filter != null) {
                 mInputFilter = filter;
                 mInputFilterHost = new InputFilterHost();
-                filter.install(mInputFilterHost);
+                try {
+                    filter.install(mInputFilterHost);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
             }
 
             nativeSetInputFilterEnabled(mPtr, filter != null);
@@ -1229,7 +1237,11 @@
     final boolean filterInputEvent(InputEvent event, int policyFlags) {
         synchronized (mInputFilterLock) {
             if (mInputFilter != null) {
-                mInputFilter.filterInputEvent(event, policyFlags);
+                try {
+                    mInputFilter.filterInputEvent(event, policyFlags);
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
                 return false;
             }
         }
@@ -1384,9 +1396,9 @@
 
     // Native callback.
     private String getDeviceAlias(String uniqueId) {
-        if (mBluetoothService != null &&
-                BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
-            return mBluetoothService.getRemoteAlias(uniqueId);
+        if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
+            // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
+            return null;
         }
         return null;
     }
@@ -1447,7 +1459,7 @@
     /**
      * Hosting interface for input filters to call back into the input manager.
      */
-    private final class InputFilterHost implements InputFilter.Host {
+    private final class InputFilterHost extends IInputFilterHost.Stub {
         private boolean mDisconnected;
 
         public void disconnectLocked() {
diff --git a/services/java/com/android/server/location/Geofence.java b/services/java/com/android/server/location/Geofence.java
new file mode 100644
index 0000000..f63607a
--- /dev/null
+++ b/services/java/com/android/server/location/Geofence.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.server.location;
+
+import android.location.Location;
+
+/**
+ * Represents a simple circular GeoFence.
+ */
+public class Geofence {
+    public final static int FLAG_ENTER = 0x01;
+    public final static int FLAG_EXIT = 0x02;
+
+    static final int STATE_UNKNOWN = 0;
+    static final int STATE_INSIDE = 1;
+    static final int STATE_OUTSIDE = 2;
+
+    final double mLatitude;
+    final double mLongitude;
+    final float mRadius;
+    final Location mLocation;
+
+    int mState;  // current state
+    double mDistance;  // current distance to center of fence
+
+    public Geofence(double latitude, double longitude, float radius, Location prevLocation) {
+        mState = STATE_UNKNOWN;
+
+        mLatitude = latitude;
+        mLongitude = longitude;
+        mRadius = radius;
+
+        mLocation = new Location("");
+        mLocation.setLatitude(latitude);
+        mLocation.setLongitude(longitude);
+
+        if (prevLocation != null) {
+            processLocation(prevLocation);
+        }
+    }
+
+    /**
+     * Process a new location.
+     * @return FLAG_ENTER or FLAG_EXIT if the fence was crossed, 0 otherwise
+     */
+    public int processLocation(Location location) {
+        mDistance = mLocation.distanceTo(location);
+
+        int prevState = mState;
+        //TODO: inside/outside detection could be made more rigorous
+        boolean inside = mDistance <= Math.max(mRadius, location.getAccuracy());
+        if (inside) {
+            mState = STATE_INSIDE;
+        } else {
+            mState = STATE_OUTSIDE;
+        }
+
+        if (prevState != 0 && mState != prevState) {
+            if (mState == STATE_INSIDE) return FLAG_ENTER;
+            if (mState == STATE_OUTSIDE) return FLAG_EXIT;
+        }
+        return 0;
+    }
+
+    public double getDistance() {
+        return mDistance;
+    }
+
+    @Override
+    public String toString() {
+        String state;
+        switch (mState) {
+            case STATE_INSIDE:
+                state = "IN";
+                break;
+            case STATE_OUTSIDE:
+                state = "OUT";
+                break;
+            default:
+                state = "?";
+        }
+        return String.format("(%.4f, %.4f r=%.0f d=%.0f %s)", mLatitude, mLongitude, mRadius,
+                mDistance, state);
+    }
+}
diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/java/com/android/server/location/GeofenceManager.java
new file mode 100644
index 0000000..b3f53ea
--- /dev/null
+++ b/services/java/com/android/server/location/GeofenceManager.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 20012 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.location;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import android.Manifest.permission;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
+    static final String TAG = "GeofenceManager";
+
+    /**
+     * Assume a maximum land speed, as a heuristic to throttle location updates.
+     * (Air travel should result in an airplane mode toggle which will
+     * force a new location update anyway).
+     */
+    static final int MAX_SPEED_M_S = 100;  // 360 km/hr (high speed train)
+
+    class GeofenceWrapper {
+        final Geofence fence;
+        final long expiry;
+        final String packageName;
+        final PendingIntent intent;
+
+        public GeofenceWrapper(Geofence fence, long expiry, String packageName,
+                PendingIntent intent) {
+            this.fence = fence;
+            this.expiry = expiry;
+            this.packageName = packageName;
+            this.intent = intent;
+        }
+    }
+
+    final Context mContext;
+    final LocationManager mLocationManager;
+    final PowerManager.WakeLock mWakeLock;
+    final Looper mLooper;  // looper thread to take location updates on
+
+    // access to members below is synchronized on this
+    Location mLastLocation;
+    List<GeofenceWrapper> mFences = new LinkedList<GeofenceWrapper>();
+
+    public GeofenceManager(Context context) {
+        mContext = context;
+        mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+        mLooper = Looper.myLooper();
+        mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this);
+    }
+
+    public void addFence(double latitude, double longitude, float radius, long expiration,
+            PendingIntent intent, int uid, String packageName) {
+        long expiry = SystemClock.elapsedRealtime() + expiration;
+        if (expiration < 0) {
+            expiry = Long.MAX_VALUE;
+        }
+        Geofence fence = new Geofence(latitude, longitude, radius, mLastLocation);
+        GeofenceWrapper fenceWrapper = new GeofenceWrapper(fence, expiry, packageName, intent);
+
+        synchronized (this) {
+            mFences.add(fenceWrapper);
+            updateProviderRequirements();
+        }
+    }
+
+    public void removeFence(PendingIntent intent) {
+        synchronized (this) {
+            Iterator<GeofenceWrapper> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceWrapper fenceWrapper = iter.next();
+                if (fenceWrapper.intent.equals(intent)) {
+                    iter.remove();
+                }
+            }
+            updateProviderRequirements();
+        }
+    }
+
+    public void removeFence(String packageName) {
+        synchronized (this) {
+            Iterator<GeofenceWrapper> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceWrapper fenceWrapper = iter.next();
+                if (fenceWrapper.packageName.equals(packageName)) {
+                    iter.remove();
+                }
+            }
+            updateProviderRequirements();
+        }
+    }
+
+    void removeExpiredFences() {
+        synchronized (this) {
+            long time = SystemClock.elapsedRealtime();
+            Iterator<GeofenceWrapper> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceWrapper fenceWrapper = iter.next();
+                if (fenceWrapper.expiry < time) {
+                    iter.remove();
+                }
+            }
+        }
+    }
+
+    void processLocation(Location location) {
+        List<PendingIntent> enterIntents = new LinkedList<PendingIntent>();
+        List<PendingIntent> exitIntents = new LinkedList<PendingIntent>();
+
+        synchronized (this) {
+            mLastLocation = location;
+
+            removeExpiredFences();
+
+            for (GeofenceWrapper fenceWrapper : mFences) {
+                int event = fenceWrapper.fence.processLocation(location);
+                if ((event & Geofence.FLAG_ENTER) != 0) {
+                    enterIntents.add(fenceWrapper.intent);
+                }
+                if ((event & Geofence.FLAG_EXIT) != 0) {
+                    exitIntents.add(fenceWrapper.intent);
+                }
+            }
+            updateProviderRequirements();
+        }
+
+        // release lock before sending intents
+        for (PendingIntent intent : exitIntents) {
+            sendIntentExit(intent);
+        }
+        for (PendingIntent intent : enterIntents) {
+            sendIntentEnter(intent);
+        }
+    }
+
+    void sendIntentEnter(PendingIntent pendingIntent) {
+        Intent intent = new Intent();
+        intent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
+        sendIntent(pendingIntent, intent);
+    }
+
+    void sendIntentExit(PendingIntent pendingIntent) {
+        Intent intent = new Intent();
+        intent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
+        sendIntent(pendingIntent, intent);
+    }
+
+    void sendIntent(PendingIntent pendingIntent, Intent intent) {
+        try {
+            mWakeLock.acquire();
+            pendingIntent.send(mContext, 0, intent, this, null, permission.ACCESS_FINE_LOCATION);
+        } catch (PendingIntent.CanceledException e) {
+            removeFence(pendingIntent);
+            mWakeLock.release();
+        }
+    }
+
+    void updateProviderRequirements() {
+        synchronized (this) {
+            double minDistance = Double.MAX_VALUE;
+            for (GeofenceWrapper alert : mFences) {
+                if (alert.fence.getDistance() < minDistance) {
+                    minDistance = alert.fence.getDistance();
+                }
+            }
+
+            if (minDistance == Double.MAX_VALUE) {
+                disableLocation();
+            } else {
+                int intervalMs = (int)(minDistance * 1000) / MAX_SPEED_M_S;
+                setLocationInterval(intervalMs);
+            }
+        }
+    }
+
+    void setLocationInterval(int intervalMs) {
+        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, intervalMs, 0, this,
+                mLooper);
+    }
+
+    void disableLocation() {
+        mLocationManager.removeUpdates(this);
+    }
+
+    @Override
+    public void onLocationChanged(Location location) {
+        processLocation(location);
+    }
+
+    @Override
+    public void onStatusChanged(String provider, int status, Bundle extras) { }
+
+    @Override
+    public void onProviderEnabled(String provider) { }
+
+    @Override
+    public void onProviderDisabled(String provider) { }
+
+    @Override
+    public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
+            String resultData, Bundle resultExtras) {
+        mWakeLock.release();
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("  Geofences:");
+        for (GeofenceWrapper fenceWrapper : mFences) {
+            pw.append("    ");
+            pw.append(fenceWrapper.packageName);
+            pw.append(" ");
+            pw.append(fenceWrapper.fence.toString());
+            pw.append("\n");
+        }
+    }
+}
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 4ad6140..8e75d94 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1078,6 +1078,9 @@
                 mLocation.setLatitude(latitude);
                 mLocation.setLongitude(longitude);
                 mLocation.setTime(timestamp);
+                // It would be nice to push the elapsed real-time timestamp
+                // further down the stack, but this is still useful
+                mLocation.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
             }
             if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
                 mLocation.setAltitude(altitude);
diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/java/com/android/server/location/LocationBasedCountryDetector.java
index d4fb8ee..38871d7 100755
--- a/services/java/com/android/server/location/LocationBasedCountryDetector.java
+++ b/services/java/com/android/server/location/LocationBasedCountryDetector.java
@@ -114,7 +114,9 @@
         for (String provider : providers) {
             Location lastKnownLocation = mLocationManager.getLastKnownLocation(provider);
             if (lastKnownLocation != null) {
-                if (bestLocation == null || bestLocation.getTime() < lastKnownLocation.getTime()) {
+                if (bestLocation == null ||
+                        bestLocation.getElapsedRealtimeNano() <
+                        lastKnownLocation.getElapsedRealtimeNano()) {
                     bestLocation = lastKnownLocation;
                 }
             }
diff --git a/services/java/com/android/server/net/NetworkAlertObserver.java b/services/java/com/android/server/net/NetworkAlertObserver.java
index 0d1c3b2..9e181c5 100644
--- a/services/java/com/android/server/net/NetworkAlertObserver.java
+++ b/services/java/com/android/server/net/NetworkAlertObserver.java
@@ -41,4 +41,7 @@
     public void interfaceAdded(String iface) {
         // ignored; interface changes come through ConnectivityService
     }
+    public void interfaceClassDataActivityChanged(String label, boolean active) {
+        // ignored; interface changes come through ConnectivityService
+    }
 }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 3501e47..ffb3fa6 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -173,6 +173,7 @@
     private static final int RADIO_UID = Process.PHONE_UID;
     private static final int LOG_UID = Process.LOG_UID;
     private static final int NFC_UID = Process.NFC_UID;
+    private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
 
     private static final boolean GET_CERTIFICATES = true;
 
@@ -208,7 +209,15 @@
      * The default maximum time to wait for the verification agent to return in
      * milliseconds.
      */
-    private static final long DEFAULT_VERIFICATION_TIMEOUT = 60 * 1000;
+    private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
+
+    /**
+     * The default response for package verification timeout.
+     *
+     * This can be either PackageManager.VERIFICATION_ALLOW or
+     * PackageManager.VERIFICATION_REJECT.
+     */
+    private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
 
     static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
 
@@ -694,6 +703,10 @@
                                 // Remove the replaced package's older resources safely now
                                 deleteOld = true;
                             }
+
+                            // Log current value of "unknown sources" setting
+                            EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
+                                getUnknownSourcesSettings());
                         }
                         // Force a gc to clear up things
                         Runtime.getRuntime().gc();
@@ -769,7 +782,18 @@
                         Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
                         mPendingVerification.remove(verificationId);
 
-                        int ret = PackageManager.INSTALL_FAILED_VERIFICATION_TIMEOUT;
+                        int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+
+                        if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
+                          Slog.i(TAG, "Continuing with installation of " + args.packageURI.toString());
+                          state.setVerifierResponse(Binder.getCallingUid(), PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
+                          try {
+                              ret = args.copyApk(mContainerService, true);
+                          } catch (RemoteException e) {
+                              Slog.e(TAG, "Could not contact the ContainerService");
+                          }
+                        }
+
                         processPendingInstall(args, ret);
 
                         mHandler.sendEmptyMessage(MCS_UNBIND);
@@ -880,6 +904,7 @@
         mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
         mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
         mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
+        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
 
         String separateProcesses = SystemProperties.get("debug.separate_processes");
         if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -5449,6 +5474,17 @@
     }
 
     /**
+     * Get the default verification agent response code.
+     *
+     * @return default verification response code
+     */
+    private int getDefaultVerificationResponse() {
+        return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
+                DEFAULT_VERIFICATION_RESPONSE);
+    }
+
+    /**
      * Check whether or not package verification has been enabled.
      *
      * @return true if verification should be performed
@@ -5459,6 +5495,17 @@
                 DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
     }
 
+    /**
+     * Get the "allow unknown sources" setting.
+     *
+     * @return the current "allow unknown sources" setting
+     */
+    private int getUnknownSourcesSettings() {
+        return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
+                -1);
+    }
+
     public void setInstallerPackageName(String targetPackage, String installerPackageName) {
         final int uid = Binder.getCallingUid();
         // writer
@@ -9459,14 +9506,20 @@
 
     @Override
     public UserInfo getUser(int userId) {
-        enforceSystemOrRoot("Only the system can remove users");
+        enforceSystemOrRoot("Only the system can query user");
         return sUserManager.getUser(userId);
     }
 
     @Override
-    public void updateUserName(int userId, String name) {
+    public void setUserName(int userId, String name) {
         enforceSystemOrRoot("Only the system can rename users");
-        sUserManager.updateUserName(userId, name);
+        sUserManager.setUserName(userId, name);
+    }
+
+    @Override
+    public ParcelFileDescriptor setUserIcon(int userId) {
+        enforceSystemOrRoot("Only the system can update users");
+        return sUserManager.setUserIcon(userId);
     }
 
     @Override
diff --git a/services/java/com/android/server/pm/UserManager.java b/services/java/com/android/server/pm/UserManager.java
index 4e9e666..738ab08 100644
--- a/services/java/com/android/server/pm/UserManager.java
+++ b/services/java/com/android/server/pm/UserManager.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm;
 
+import static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 
@@ -24,6 +27,7 @@
 import android.content.pm.UserInfo;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
 import android.os.UserId;
 import android.util.Log;
@@ -34,6 +38,7 @@
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -44,10 +49,15 @@
 import org.xmlpull.v1.XmlSerializer;
 
 public class UserManager {
+
+    private static final String TAG = "UserManager";
+
     private static final String TAG_NAME = "name";
 
     private static final String ATTR_FLAGS = "flags";
 
+    private static final String ATTR_ICON_PATH = "icon";
+
     private static final String ATTR_ID = "id";
 
     private static final String TAG_USERS = "users";
@@ -58,6 +68,7 @@
 
     private static final String USER_INFO_DIR = "system" + File.separator + "users";
     private static final String USER_LIST_FILENAME = "userlist.xml";
+    private static final String USER_PHOTO_FILENAME = "photo.png";
 
     private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
 
@@ -114,7 +125,7 @@
         }
     }
 
-    public void updateUserName(int userId, String name) {
+    public void setUserName(int userId, String name) {
         synchronized (mUsers) {
             UserInfo info = mUsers.get(userId);
             if (name != null && !name.equals(info.name)) {
@@ -124,6 +135,39 @@
         }
     }
 
+    public ParcelFileDescriptor setUserIcon(int userId) {
+        synchronized (mUsers) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null) return null;
+            ParcelFileDescriptor fd = updateIconBitmapLocked(info);
+            if (fd != null) {
+                writeUserLocked(info);
+            }
+            return fd;
+        }
+    }
+
+    private ParcelFileDescriptor updateIconBitmapLocked(UserInfo info) {
+        try {
+            File dir = new File(mUsersDir, Integer.toString(info.id));
+            File file = new File(dir, USER_PHOTO_FILENAME);
+            if (!dir.exists()) {
+                dir.mkdir();
+                FileUtils.setPermissions(
+                        dir.getPath(),
+                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                        -1, -1);
+            }
+            ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
+                    MODE_CREATE|MODE_READ_WRITE);
+            info.iconPath = file.getAbsolutePath();
+            return fd;
+        } catch (FileNotFoundException e) {
+            Slog.w(TAG, "Error setting photo for user ", e);
+        }
+        return null;
+    }
+
     /**
      * Returns an array of user ids. This array is cached here for quick access, so do not modify or
      * cache it elsewhere.
@@ -187,7 +231,7 @@
 
     private void fallbackToSingleUserLocked() {
         // Create the primary user
-        UserInfo primary = new UserInfo(0, "Primary",
+        UserInfo primary = new UserInfo(0, "Primary", null,
                 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
         mUsers.put(0, primary);
         updateUserIdsLocked();
@@ -219,6 +263,9 @@
             serializer.startTag(null, TAG_USER);
             serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
             serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
+            if (userInfo.iconPath != null) {
+                serializer.attribute(null,  ATTR_ICON_PATH, userInfo.iconPath);
+            }
 
             serializer.startTag(null, TAG_NAME);
             serializer.text(userInfo.name);
@@ -286,6 +333,7 @@
     private UserInfo readUser(int id) {
         int flags = 0;
         String name = null;
+        String iconPath = null;
 
         FileInputStream fis = null;
         try {
@@ -312,6 +360,7 @@
                 }
                 String flagString = parser.getAttributeValue(null, ATTR_FLAGS);
                 flags = Integer.parseInt(flagString);
+                iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
 
                 while ((type = parser.next()) != XmlPullParser.START_TAG
                         && type != XmlPullParser.END_DOCUMENT) {
@@ -324,7 +373,7 @@
                 }
             }
 
-            UserInfo userInfo = new UserInfo(id, name, flags);
+            UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
             return userInfo;
 
         } catch (IOException ioe) {
@@ -342,7 +391,7 @@
 
     public UserInfo createUser(String name, int flags) {
         int userId = getNextAvailableId();
-        UserInfo userInfo = new UserInfo(userId, name, flags);
+        UserInfo userInfo = new UserInfo(userId, name, null, flags);
         File userPath = new File(mBaseUserPath, Integer.toString(userId));
         if (!createPackageFolders(userId, userPath)) {
             return null;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
similarity index 97%
rename from services/java/com/android/server/PowerManagerService.java
rename to services/java/com/android/server/power/PowerManagerService.java
index 888ec69..2940b70 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.power;
 
 import com.android.internal.app.IBatteryStats;
+import com.android.server.BatteryService;
+import com.android.server.EventLogTags;
+import com.android.server.LightsService;
+import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
-import com.android.server.pm.ShutdownThread;
 
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
@@ -62,7 +65,6 @@
 import static android.provider.Settings.System.DIM_SCREEN;
 import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
-import static android.provider.Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ;
 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
@@ -84,20 +86,21 @@
     private static final String TAG = "PowerManagerService";
     static final String PARTIAL_NAME = "PowerManagerService";
 
+    // could be either static or controllable at runtime
+    private static final boolean DEBUG = false;
+    private static final boolean DEBUG_PROXIMITY_SENSOR = (false || DEBUG);
+    private static final boolean DEBUG_LIGHT_SENSOR = (false || DEBUG);
+    private static final boolean DEBUG_LIGHT_ANIMATION = (false || DEBUG);
+    private static final boolean DEBUG_SCREEN_ON = false;
+
     // Wake lock that ensures that the CPU is running.  The screen might not be on.
     private static final int PARTIAL_WAKE_LOCK_ID = 1;
 
     // Wake lock that ensures that the screen is on.
     private static final int FULL_WAKE_LOCK_ID = 2;
 
-    static final boolean DEBUG_SCREEN_ON = false;
-
     private static final boolean LOG_PARTIAL_WL = false;
 
-    // Indicates whether touch-down cycles should be logged as part of the
-    // LOG_POWER_SCREEN_STATE log events
-    private static final boolean LOG_TOUCH_DOWNS = true;
-
     private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
                                         | PowerManager.SCREEN_DIM_WAKE_LOCK
                                         | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
@@ -296,17 +299,6 @@
     private static final int ANIM_SETTING_ON = 0x01;
     private static final int ANIM_SETTING_OFF = 0x10;
 
-    // Used when logging number and duration of touch-down cycles
-    private long mTotalTouchDownTime;
-    private long mLastTouchDown;
-    private int mTouchCycles;
-
-    // could be either static or controllable at runtime
-    private static final boolean mSpew = false;
-    private static final boolean mDebugProximitySensor = (false || mSpew);
-    private static final boolean mDebugLightSensor = (false || mSpew);
-    private static final boolean mDebugLightAnimation = (false || mSpew);
-
     private native void nativeInit();
     private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
     private native void nativeStartSurfaceFlingerAnimation(int mode);
@@ -532,7 +524,7 @@
         }
     }
 
-    PowerManagerService() {
+    public PowerManagerService() {
         // Hack to get our uid...  should have a func for this.
         long token = Binder.clearCallingIdentity();
         MY_UID = Process.myUid();
@@ -550,7 +542,7 @@
 
     private ContentQueryMap mSettings;
 
-    void init(Context context, LightsService lights, IActivityManager activity,
+    public void init(Context context, LightsService lights, IActivityManager activity,
             BatteryService battery) {
         mLightsService = lights;
         mContext = context;
@@ -707,7 +699,7 @@
     /**
      * Low-level function turn the device off immediately, without trying
      * to be clean.  Most people should use
-     * {@link com.android.server.pm.internal.app.ShutdownThread} for a clean shutdown.
+     * {@link com.android.server.power.internal.app.ShutdownThread} for a clean shutdown.
      */
     public static void lowLevelShutdown() {
         nativeShutdown();
@@ -850,7 +842,7 @@
 
     public void acquireWakeLockLocked(int flags, IBinder lock, int uid, int pid, String tag,
             WorkSource ws) {
-        if (mSpew) {
+        if (DEBUG) {
             Slog.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
         }
 
@@ -939,7 +931,7 @@
                         mProximitySensorActive = false;
                     }
 
-                    if (mSpew) {
+                    if (DEBUG) {
                         Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
                                 + " mWakeLockState=0x"
                                 + Integer.toHexString(mWakeLockState)
@@ -947,7 +939,7 @@
                                 + Integer.toHexString(oldWakeLockState));
                     }
                 } else {
-                    if (mSpew) {
+                    if (DEBUG) {
                         Slog.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
                                 + " mLocks.gatherState()=0x"
                                 + Integer.toHexString(mLocks.gatherState())
@@ -962,7 +954,9 @@
             if (newlock) {
                 mPartialCount++;
                 if (mPartialCount == 1) {
-                    if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
+                    if (LOG_PARTIAL_WL) {
+                        EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
+                    }
                 }
             }
             nativeAcquireWakeLock(PARTIAL_WAKE_LOCK_ID, PARTIAL_NAME);
@@ -1017,7 +1011,7 @@
             return;
         }
 
-        if (mSpew) {
+        if (DEBUG) {
             Slog.d(TAG, "releaseWakeLock flags=0x"
                     + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
         }
@@ -1029,7 +1023,7 @@
                     if (mProximitySensorActive &&
                             ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
                         // wait for proximity sensor to go negative before disabling sensor
-                        if (mDebugProximitySensor) {
+                        if (DEBUG_PROXIMITY_SENSOR) {
                             Slog.d(TAG, "waiting for proximity sensor to go negative");
                         }
                     } else {
@@ -1048,7 +1042,9 @@
         else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
             mPartialCount--;
             if (mPartialCount == 0) {
-                if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
+                if (LOG_PARTIAL_WL) {
+                    EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
+                }
                 nativeReleaseWakeLock(PARTIAL_NAME);
             }
         }
@@ -1333,7 +1329,7 @@
                         nextState = SCREEN_BRIGHT;
                     }
                 }
-                if (mSpew) {
+                if (DEBUG) {
                     Slog.d(TAG, "setTimeoutLocked now=" + now
                             + " timeoutOverride=" + timeoutOverride
                             + " nextState=" + nextState + " when=" + when);
@@ -1363,7 +1359,7 @@
         public void run()
         {
             synchronized (mLocks) {
-                if (mSpew) {
+                if (DEBUG) {
                     Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
                 }
 
@@ -1518,7 +1514,7 @@
                         // ignore it
                     }
 
-                    if (mSpew) {
+                    if (DEBUG) {
                         Slog.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
                     }
                     if (mContext != null && ActivityManagerNative.isSystemReady()) {
@@ -1585,23 +1581,6 @@
         }
     };
 
-    void logPointerUpEvent() {
-        if (LOG_TOUCH_DOWNS) {
-            mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
-            mLastTouchDown = 0;
-        }
-    }
-
-    void logPointerDownEvent() {
-        if (LOG_TOUCH_DOWNS) {
-            // If we are not already timing a down/up sequence
-            if (mLastTouchDown == 0) {
-                mLastTouchDown = SystemClock.elapsedRealtime();
-                mTouchCycles++;
-            }
-        }
-    }
-
     /**
      * Prevents the screen from turning on even if it *should* turn on due
      * to a subsequent full wake lock being acquired.
@@ -1663,7 +1642,7 @@
                 // handles the case where the screen is currently off because of
                 // a prior preventScreenOn(true) call.)
                 if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
-                    if (mSpew) {
+                    if (DEBUG) {
                         Slog.d(TAG,
                               "preventScreenOn: turning on after a prior preventScreenOn(true)!");
                     }
@@ -1683,7 +1662,7 @@
     public void setScreenBrightnessOverride(int brightness) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
 
-        if (mSpew) Slog.d(TAG, "setScreenBrightnessOverride " + brightness);
+        if (DEBUG) Slog.d(TAG, "setScreenBrightnessOverride " + brightness);
         synchronized (mLocks) {
             if (mScreenBrightnessOverride != brightness) {
                 mScreenBrightnessOverride = brightness;
@@ -1697,7 +1676,7 @@
     public void setButtonBrightnessOverride(int brightness) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
 
-        if (mSpew) Slog.d(TAG, "setButtonBrightnessOverride " + brightness);
+        if (DEBUG) Slog.d(TAG, "setButtonBrightnessOverride " + brightness);
          synchronized (mLocks) {
            if (mButtonBrightnessOverride != brightness) {
                 mButtonBrightnessOverride = brightness;
@@ -1795,7 +1774,7 @@
         synchronized (mLocks) {
             int err;
 
-            if (mSpew) {
+            if (DEBUG) {
                 Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
                         + " newState=0x" + Integer.toHexString(newState)
                         + " noChangeLights=" + noChangeLights
@@ -1826,7 +1805,7 @@
             boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
             boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
 
-            if (mSpew) {
+            if (DEBUG) {
                 Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState
                         + " newState=" + newState + " noChangeLights=" + noChangeLights);
                 Slog.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
@@ -1845,7 +1824,7 @@
 
             if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) {
                 if (mPolicy != null && mPolicy.isScreenSaverEnabled()) {
-                    if (mSpew) {
+                    if (DEBUG) {
                         Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen");
                     }
                     if (mPolicy.startScreenSaver()) {
@@ -1872,13 +1851,13 @@
                     // seconds to prevent a buggy app from disabling the
                     // screen forever; see forceReenableScreen().)
                     boolean reallyTurnScreenOn = true;
-                    if (mSpew) {
+                    if (DEBUG) {
                         Slog.d(TAG, "- turning screen on...  mPreventScreenOn = "
                               + mPreventScreenOn);
                     }
 
                     if (mPreventScreenOn) {
-                        if (mSpew) {
+                        if (DEBUG) {
                             Slog.d(TAG, "- PREVENTING screen from really turning on!");
                         }
                         reallyTurnScreenOn = false;
@@ -1900,11 +1879,7 @@
                         err = 0;
                     }
 
-                    mLastTouchDown = 0;
-                    mTotalTouchDownTime = 0;
-                    mTouchCycles = 0;
-                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
-                            mTotalTouchDownTime, mTouchCycles);
+                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason, 0, 0);
                     if (err == 0) {
                         sendNotificationLocked(true, -1);
                         // Update the lights *after* taking care of turning the
@@ -1943,7 +1918,6 @@
                         err = screenOffFinishedAnimatingLocked(reason);
                     } else {
                         err = 0;
-                        mLastTouchDown = 0;
                     }
                 }
             } else if (stateChanged) {
@@ -1969,9 +1943,7 @@
         // I don't think we need to check the current state here because all of these
         // Power.setScreenState and sendNotificationLocked can both handle being
         // called multiple times in the same state. -joeo
-        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime,
-                mTouchCycles);
-        mLastTouchDown = 0;
+        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, 0, 0);
         int err = setScreenStateLocked(false);
         if (err == 0) {
             mScreenOffReason = reason;
@@ -2142,7 +2114,7 @@
             }
         }
 
-        if (mSpew) {
+        if (DEBUG) {
             Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)
                     + " dimMask=0x" + Integer.toHexString(dimMask)
                     + " onMask=0x" + Integer.toHexString(onMask)
@@ -2153,7 +2125,7 @@
         }
 
         if (offMask != 0) {
-            if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
+            if (DEBUG) Slog.i(TAG, "Setting brightess off: " + offMask);
             setLightBrightness(offMask, PowerManager.BRIGHTNESS_OFF);
         }
         if (dimMask != 0) {
@@ -2162,7 +2134,7 @@
                     brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
                 brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
             }
-            if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
+            if (DEBUG) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
             setLightBrightness(dimMask, brightness);
         }
         if (onMask != 0) {
@@ -2171,7 +2143,7 @@
                     brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
                 brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
             }
-            if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
+            if (DEBUG) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
             setLightBrightness(onMask, brightness);
         }
     }
@@ -2210,7 +2182,7 @@
                         int value = msg.arg2;
                         long tStart = SystemClock.uptimeMillis();
                         if ((mask & SCREEN_BRIGHT_BIT) != 0) {
-                            if (mDebugLightAnimation) Slog.v(TAG, "Set brightness: " + value);
+                            if (DEBUG_LIGHT_ANIMATION) Slog.v(TAG, "Set brightness: " + value);
                             mLcdLight.setBrightness(value, brightnessMode);
                         }
                         long elapsed = SystemClock.uptimeMillis() - tStart;
@@ -2272,7 +2244,7 @@
                         }
                     }
 
-                    if (mDebugLightAnimation) {
+                    if (DEBUG_LIGHT_ANIMATION) {
                         Slog.v(TAG, "Animating light: " + "start:" + startValue
                                 + ", end:" + endValue + ", elapsed:" + elapsed
                                 + ", duration:" + duration + ", current:" + currentValue
@@ -2284,7 +2256,7 @@
                     if (turningOff && !mHeadless && !mAnimateScreenLights) {
                         int mode = mScreenOffReason == OFF_BECAUSE_OF_PROX_SENSOR
                                 ? 0 : mAnimationSetting;
-                        if (mDebugLightAnimation) {
+                        if (DEBUG_LIGHT_ANIMATION) {
                             Slog.v(TAG, "Doing power-off anim, mode=" + mode);
                         }
                         mScreenBrightnessHandler.obtainMessage(ANIMATE_POWER_OFF, mode, 0)
@@ -2345,7 +2317,7 @@
                 duration = (int) (mWindowScaleAnimation * animationDuration);
                 startTimeMillis = SystemClock.elapsedRealtime();
 
-                if (mDebugLightAnimation) {
+                if (DEBUG_LIGHT_ANIMATION) {
                     Slog.v(TAG, "animateTo(target=" + target
                             + ", sensor=" + sensorTarget
                             + ", mask=" + mask
@@ -2393,13 +2365,13 @@
     }
 
     private int getPreferredBrightness() {
+        int brightness = mScreenBrightnessSetting;
         if (mScreenBrightnessOverride >= 0) {
-            return mScreenBrightnessOverride;
+            brightness = mScreenBrightnessOverride;
         } else if (mLightSensorScreenBrightness >= 0 && mUseSoftwareAutoBrightness
                 && mAutoBrightessEnabled) {
-            return mLightSensorScreenBrightness;
+            brightness = mLightSensorScreenBrightness;
         }
-        final int brightness = mScreenBrightnessSetting;
          // Don't let applications turn the screen all the way off
         return Math.max(brightness, mScreenBrightnessDim);
     }
@@ -2537,7 +2509,7 @@
         }
 
         synchronized (mLocks) {
-            if (mSpew) {
+            if (DEBUG) {
                 Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
                         + " mUserActivityAllowed=" + mUserActivityAllowed
                         + " mUserState=0x" + Integer.toHexString(mUserState)
@@ -2687,13 +2659,13 @@
     }
 
     private void lightSensorChangedLocked(int value, boolean immediate) {
-        if (mDebugLightSensor) {
+        if (DEBUG_LIGHT_SENSOR) {
             Slog.d(TAG, "lightSensorChangedLocked value=" + value + " immediate=" + immediate);
         }
 
         // Don't do anything if the screen is off.
         if ((mPowerState & SCREEN_ON_BIT) == 0) {
-            if (mDebugLightSensor) {
+            if (DEBUG_LIGHT_SENSOR) {
                 Slog.d(TAG, "dropping lightSensorChangedLocked because screen is off");
             }
             return;
@@ -2717,7 +2689,7 @@
                 mLightSensorButtonBrightness = buttonValue;
                 mLightSensorKeyboardBrightness = keyboardValue;
 
-                if (mDebugLightSensor) {
+                if (DEBUG_LIGHT_SENSOR) {
                     Slog.d(TAG, "lcdValue " + lcdValue);
                     Slog.d(TAG, "buttonValue " + buttonValue);
                     Slog.d(TAG, "keyboardValue " + keyboardValue);
@@ -2826,7 +2798,7 @@
     }
 
     private void goToSleepLocked(long time, int reason) {
-        if (mSpew) {
+        if (DEBUG) {
             Exception ex = new Exception();
             ex.fillInStackTrace();
             Slog.d(TAG, "goToSleep mLastEventTime=" + mLastEventTime + " time=" + time
@@ -2854,7 +2826,7 @@
             }
             if (!proxLock) {
                 mProxIgnoredBecauseScreenTurnedOff = true;
-                if (mDebugProximitySensor) {
+                if (DEBUG_PROXIMITY_SENSOR) {
                     Slog.d(TAG, "setting mProxIgnoredBecauseScreenTurnedOff");
                 }
             }
@@ -2877,7 +2849,7 @@
 
     public void setKeyboardVisibility(boolean visible) {
         synchronized (mLocks) {
-            if (mSpew) {
+            if (DEBUG) {
                 Slog.d(TAG, "setKeyboardVisibility: " + visible);
             }
             if (mKeyboardVisible != visible) {
@@ -2906,7 +2878,7 @@
      * short screen timeout when keyguard is unhidden.
      */
     public void enableUserActivity(boolean enabled) {
-        if (mSpew) {
+        if (DEBUG) {
             Slog.d(TAG, "enableUserActivity " + enabled);
         }
         synchronized (mLocks) {
@@ -2967,7 +2939,7 @@
                 mDimDelay = -1;
             }
         }
-        if (mSpew) {
+        if (DEBUG) {
             Slog.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
                     + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
                     + " mDimScreen=" + mDimScreen);
@@ -3043,7 +3015,7 @@
                     result |= wl.minState;
                 }
             }
-            if (mDebugProximitySensor) {
+            if (DEBUG_PROXIMITY_SENSOR) {
                 Slog.d(TAG, "reactivateScreenLocksLocked mProxIgnoredBecauseScreenTurnedOff="
                         + mProxIgnoredBecauseScreenTurnedOff);
             }
@@ -3070,7 +3042,7 @@
         return mPolicy;
     }
 
-    void systemReady() {
+    public void systemReady() {
         mSensorManager = new SystemSensorManager(mHandlerThread.getLooper());
         mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
         // don't bother with the light sensor if auto brightness is handled in hardware
@@ -3181,7 +3153,7 @@
     }
 
     private void enableProximityLockLocked() {
-        if (mDebugProximitySensor) {
+        if (DEBUG_PROXIMITY_SENSOR) {
             Slog.d(TAG, "enableProximityLockLocked");
         }
         if (!mProximitySensorEnabled) {
@@ -3198,7 +3170,7 @@
     }
 
     private void disableProximityLockLocked() {
-        if (mDebugProximitySensor) {
+        if (DEBUG_PROXIMITY_SENSOR) {
             Slog.d(TAG, "disableProximityLockLocked");
         }
         if (mProximitySensorEnabled) {
@@ -3216,7 +3188,7 @@
             }
             if (mProximitySensorActive) {
                 mProximitySensorActive = false;
-                if (mDebugProximitySensor) {
+                if (DEBUG_PROXIMITY_SENSOR) {
                     Slog.d(TAG, "disableProximityLockLocked mProxIgnoredBecauseScreenTurnedOff="
                             + mProxIgnoredBecauseScreenTurnedOff);
                 }
@@ -3228,7 +3200,7 @@
     }
 
     private void proximityChangedLocked(boolean active) {
-        if (mDebugProximitySensor) {
+        if (DEBUG_PROXIMITY_SENSOR) {
             Slog.d(TAG, "proximityChangedLocked, active: " + active);
         }
         if (!mProximitySensorEnabled) {
@@ -3236,7 +3208,7 @@
             return;
         }
         if (active) {
-            if (mDebugProximitySensor) {
+            if (DEBUG_PROXIMITY_SENSOR) {
                 Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
                         + mProxIgnoredBecauseScreenTurnedOff);
             }
@@ -3250,7 +3222,7 @@
             // temporarily set mUserActivityAllowed to true so this will work
             // even when the keyguard is on.
             mProximitySensorActive = false;
-            if (mDebugProximitySensor) {
+            if (DEBUG_PROXIMITY_SENSOR) {
                 Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
                         + mProxIgnoredBecauseScreenTurnedOff);
             }
@@ -3266,7 +3238,7 @@
     }
 
     private void enableLightSensorLocked(boolean enable) {
-        if (mDebugLightSensor) {
+        if (DEBUG_LIGHT_SENSOR) {
             Slog.d(TAG, "enableLightSensorLocked enable=" + enable
                     + " mLightSensorEnabled=" + mLightSensorEnabled
                     + " mAutoBrightessEnabled=" + mAutoBrightessEnabled
@@ -3317,7 +3289,7 @@
                 boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
                         distance < mProximitySensor.getMaximumRange());
 
-                if (mDebugProximitySensor) {
+                if (DEBUG_PROXIMITY_SENSOR) {
                     Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);
                 }
                 if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
@@ -3379,7 +3351,7 @@
     SensorEventListener mLightListener = new SensorEventListener() {
         @Override
         public void onSensorChanged(SensorEvent event) {
-            if (mDebugLightSensor) {
+            if (DEBUG_LIGHT_SENSOR) {
                 Slog.d(TAG, "onSensorChanged: light value: " + event.values[0]);
             }
             synchronized (mLocks) {
@@ -3389,7 +3361,7 @@
                 }
                 handleLightSensorValue((int)event.values[0], mWaitingForFirstLightSensor);
                 if (mWaitingForFirstLightSensor && !mPreparingForScreenOn) {
-                    if (mDebugLightAnimation) {
+                    if (DEBUG_LIGHT_ANIMATION) {
                         Slog.d(TAG, "onSensorChanged: Clearing mWaitingForFirstLightSensor.");
                     }
                     mWaitingForFirstLightSensor = false;
diff --git a/services/java/com/android/server/pm/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java
similarity index 96%
rename from services/java/com/android/server/pm/ShutdownThread.java
rename to services/java/com/android/server/power/ShutdownThread.java
index 3675d41..a3770d7 100644
--- a/services/java/com/android/server/pm/ShutdownThread.java
+++ b/services/java/com/android/server/power/ShutdownThread.java
@@ -15,7 +15,7 @@
  */
 
  
-package com.android.server.pm;
+package com.android.server.power;
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
@@ -23,7 +23,7 @@
 import android.app.IActivityManager;
 import android.app.ProgressDialog;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothManager;
 import android.nfc.NfcAdapter;
 import android.nfc.INfcAdapter;
 import android.content.BroadcastReceiver;
@@ -43,7 +43,6 @@
 import android.os.storage.IMountShutdownObserver;
 
 import com.android.internal.telephony.ITelephony;
-import com.android.server.PowerManagerService;
 
 import android.util.Log;
 import android.view.WindowManager;
@@ -385,9 +384,9 @@
                         INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc"));
                 final ITelephony phone =
                         ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
-                final IBluetooth bluetooth =
-                        IBluetooth.Stub.asInterface(ServiceManager.checkService(
-                                BluetoothAdapter.BLUETOOTH_SERVICE));
+                final IBluetoothManager bluetooth =
+                        IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
+                                BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
 
                 try {
                     nfcOff = nfc == null ||
@@ -402,8 +401,7 @@
                 }
 
                 try {
-                    bluetoothOff = bluetooth == null ||
-                                   bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
+                    bluetoothOff = bluetooth == null || !bluetooth.isEnabled();
                     if (!bluetoothOff) {
                         Log.w(TAG, "Disabling Bluetooth...");
                         bluetooth.disable(false);  // disable but don't persist new state
@@ -429,8 +427,7 @@
                 while (SystemClock.elapsedRealtime() < endTime) {
                     if (!bluetoothOff) {
                         try {
-                            bluetoothOff =
-                                    bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
+                            bluetoothOff = !bluetooth.isEnabled();
                         } catch (RemoteException ex) {
                             Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
                             bluetoothOff = true;
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 13e8bc5..691e2aa 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -10,10 +10,8 @@
 import android.view.animation.Transformation;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
-/**
- *
- */
 public class AppWindowAnimator {
     static final String TAG = "AppWindowAnimator";
 
@@ -48,12 +46,15 @@
     Animation thumbnailAnimation;
     final Transformation thumbnailTransformation = new Transformation();
 
+    /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
+    ArrayList<WindowStateAnimator> mAllAppWinAnimators;
+
     static final Animation sDummyAnimation = new DummyAnimation();
 
-    public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) {
-        mService = service;
+    public AppWindowAnimator(final AppWindowToken atoken) {
         mAppToken = atoken;
-        mAnimator = service.mAnimator;
+        mService = atoken.service;
+        mAnimator = atoken.mAnimator;
     }
 
     public void setAnimation(Animation anim, boolean initialized) {
@@ -123,7 +124,7 @@
             if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
                 mService.setInputMethodAnimLayerAdjustment(adj);
             }
-            if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
+            if (w == mAnimator.mWallpaperTarget && mAnimator.mLowerWallpaperTarget == null) {
                 mService.setWallpaperAnimLayerAdjustmentLocked(adj);
             }
         }
@@ -168,7 +169,7 @@
         }
         transformation.clear();
         final boolean more = animation.getTransformation(currentTime, transformation);
-        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+        if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
             TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
         if (!more) {
             animation = null;
@@ -255,9 +256,9 @@
 
         transformation.clear();
 
-        final int N = mAppToken.windows.size();
+        final int N = mAllAppWinAnimators.size();
         for (int i=0; i<N; i++) {
-            mAppToken.windows.get(i).mWinAnimator.finishExit();
+            mAllAppWinAnimators.get(i).finishExit();
         }
         mAppToken.updateReportedVisibilityLocked();
 
@@ -266,9 +267,9 @@
 
     boolean showAllWindowsLocked() {
         boolean isAnimating = false;
-        final int NW = mAppToken.allAppWindows.size();
+        final int NW = mAllAppWinAnimators.size();
         for (int i=0; i<NW; i++) {
-            WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator;
+            WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i);
             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                     "performing show on: " + winAnimator);
             winAnimator.performShowLocked();
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 6ecbb8e..13b072c 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -104,7 +104,7 @@
         appToken = _token;
         mInputApplicationHandle = new InputApplicationHandle(this);
         mAnimator = service.mAnimator;
-        mAppAnimator = new AppWindowAnimator(_service, this);
+        mAppAnimator = new AppWindowAnimator(this);
     }
 
     void sendAppVisibilityToClients() {
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 285d230..595cc47 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -128,7 +128,7 @@
         return 0; // abort dispatching
     }
 
-    private void addInputWindowHandleLw(InputWindowHandle windowHandle) {
+    private void addInputWindowHandleLw(final InputWindowHandle windowHandle) {
         if (mInputWindowHandles == null) {
             mInputWindowHandles = new InputWindowHandle[16];
         }
@@ -139,6 +139,44 @@
         mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
     }
 
+    private void addInputWindowHandleLw(final InputWindowHandle inputWindowHandle,
+            final WindowState child, final int flags, final int type,
+            final boolean isVisible, final boolean hasFocus, final boolean hasWallpaper) {
+        // Add a window to our list of input windows.
+        inputWindowHandle.name = child.toString();
+        inputWindowHandle.layoutParamsFlags = flags;
+        inputWindowHandle.layoutParamsType = type;
+        inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+        inputWindowHandle.visible = isVisible;
+        inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
+        inputWindowHandle.hasFocus = hasFocus;
+        inputWindowHandle.hasWallpaper = hasWallpaper;
+        inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+        inputWindowHandle.layer = child.mLayer;
+        inputWindowHandle.ownerPid = child.mSession.mPid;
+        inputWindowHandle.ownerUid = child.mSession.mUid;
+        inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
+
+        final Rect frame = child.mFrame;
+        inputWindowHandle.frameLeft = frame.left;
+        inputWindowHandle.frameTop = frame.top;
+        inputWindowHandle.frameRight = frame.right;
+        inputWindowHandle.frameBottom = frame.bottom;
+
+        if (child.mGlobalScale != 1) {
+            // If we are scaling the window, input coordinates need
+            // to be inversely scaled to map from what is on screen
+            // to what is actually being touched in the UI.
+            inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
+        } else {
+            inputWindowHandle.scaleFactor = 1;
+        }
+
+        child.getTouchableRegion(inputWindowHandle.touchableRegion);
+
+        addInputWindowHandleLw(inputWindowHandle);
+    }
+
     private void clearInputWindowHandlesLw() {
         while (mInputWindowHandleCount != 0) {
             mInputWindowHandles[--mInputWindowHandleCount] = null;
@@ -164,6 +202,9 @@
         // out to be difficult because only the native code knows for sure which window
         // currently has touch focus.
         final ArrayList<WindowState> windows = mService.mWindows;
+        final WindowStateAnimator universeBackground = mService.mAnimator.mUniverseBackground;
+        final int aboveUniverseLayer = mService.mAnimator.mAboveUniverseLayer;
+        boolean addedUniverse = false;
 
         // If there's a drag in flight, provide a pseudowindow to catch drag input
         final boolean inDrag = (mService.mDragState != null);
@@ -209,39 +250,20 @@
                 mService.mDragState.sendDragStartedIfNeededLw(child);
             }
 
-            // Add a window to our list of input windows.
-            inputWindowHandle.name = child.toString();
-            inputWindowHandle.layoutParamsFlags = flags;
-            inputWindowHandle.layoutParamsType = type;
-            inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
-            inputWindowHandle.visible = isVisible;
-            inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
-            inputWindowHandle.hasFocus = hasFocus;
-            inputWindowHandle.hasWallpaper = hasWallpaper;
-            inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
-            inputWindowHandle.layer = child.mLayer;
-            inputWindowHandle.ownerPid = child.mSession.mPid;
-            inputWindowHandle.ownerUid = child.mSession.mUid;
-            inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
-
-            final Rect frame = child.mFrame;
-            inputWindowHandle.frameLeft = frame.left;
-            inputWindowHandle.frameTop = frame.top;
-            inputWindowHandle.frameRight = frame.right;
-            inputWindowHandle.frameBottom = frame.bottom;
-
-            if (child.mGlobalScale != 1) {
-                // If we are scaling the window, input coordinates need
-                // to be inversely scaled to map from what is on screen
-                // to what is actually being touched in the UI.
-                inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
-            } else {
-                inputWindowHandle.scaleFactor = 1;
+            if (universeBackground != null && !addedUniverse
+                    && child.mBaseLayer < aboveUniverseLayer) {
+                final WindowState u = universeBackground.mWin;
+                if (u.mInputChannel != null && u.mInputWindowHandle != null) {
+                    addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags,
+                            u.mAttrs.type, true, u == mInputFocus, false);
+                }
+                addedUniverse = true;
             }
 
-            child.getTouchableRegion(inputWindowHandle.touchableRegion);
-
-            addInputWindowHandleLw(inputWindowHandle);
+            if (child.mWinAnimator != universeBackground) {
+                addInputWindowHandleLw(inputWindowHandle, child, flags, type,
+                        isVisible, hasFocus, hasWallpaper);
+            }
         }
 
         // Send windows to native code.
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 61c0e9c..34372fa 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -389,6 +389,20 @@
         mService.wallpaperCommandComplete(window, result);
     }
 
+    public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
+            float dsdx, float dtdx, float dsdy, float dtdy) {
+        synchronized(mService.mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                mService.setUniverseTransformLocked(
+                        mService.windowForClientLocked(this, window, true),
+                        alpha, offx, offy, dsdx, dtdx, dsdy, dtdy);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
     void windowAddedLocked() {
         if (mSurfaceSession == null) {
             if (WindowManagerService.localLOGV) Slog.v(
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 62cf711..0b76fec 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -8,19 +8,21 @@
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
 
-import static com.android.server.wm.WindowManagerService.H.SET_DIM_PARAMETERS;
+import static com.android.server.wm.WindowManagerService.H.UPDATE_ANIM_PARAMETERS;
 
 import android.content.Context;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Slog;
 import android.view.Surface;
-import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 
 import com.android.internal.policy.impl.PhoneWindowManager;
+import com.android.server.wm.WindowManagerService.AppWindowAnimParams;
+import com.android.server.wm.WindowManagerService.LayoutToAnimatorParams;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -32,13 +34,6 @@
 public class WindowAnimator {
     private static final String TAG = "WindowAnimator";
 
-    // mForceHiding states.
-    private static final int KEYGUARD_NOT_SHOWN     = 0;
-    private static final int KEYGUARD_ANIMATING_IN  = 1;
-    private static final int KEYGUARD_SHOWN         = 2;
-    private static final int KEYGUARD_ANIMATING_OUT = 3;
-    int mForceHiding;
-
     final WindowManagerService mService;
     final Context mContext;
     final WindowManagerPolicy mPolicy;
@@ -46,8 +41,9 @@
     ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
 
     boolean mAnimating;
-    WindowState mWindowAnimationBackground;
-    int mWindowAnimationBackgroundColor;
+
+    final Runnable mAnimationRunnable;
+
     int mAdjResult;
 
     int mPendingLayoutChanges;
@@ -71,11 +67,14 @@
     // Window currently running an animation that has requested it be detached
     // from the wallpaper.  This means we need to ensure the wallpaper is
     // visible behind it in case it animates in a way that would allow it to be
-    // seen.
+    // seen. If multiple windows satisfy this, use the lowest window.
     WindowState mWindowDetachedWallpaper = null;
-    WindowState mDetachedWallpaper = null;
+
     DimSurface mWindowAnimationBackgroundSurface = null;
 
+    WindowStateAnimator mUniverseBackground = null;
+    int mAboveUniverseLayer = 0;
+
     int mBulkUpdateParams = 0;
 
     DimAnimator mDimAnimator = null;
@@ -84,18 +83,125 @@
     static final int WALLPAPER_ACTION_PENDING = 1;
     int mPendingActions;
 
-    WindowAnimator(final WindowManagerService service, final Context context,
-            final WindowManagerPolicy policy) {
+    WindowState mWallpaperTarget = null;
+    AppWindowAnimator mWpAppAnimator = null;
+    WindowState mLowerWallpaperTarget = null;
+    WindowState mUpperWallpaperTarget = null;
+
+    ArrayList<AppWindowAnimator> mAppAnimators = new ArrayList<AppWindowAnimator>();
+
+    ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+
+    /** Parameters being passed from this into mService. */
+    static class AnimatorToLayoutParams {
+        boolean mUpdateQueued;
+        int mBulkUpdateParams;
+        int mPendingLayoutChanges;
+        WindowState mWindowDetachedWallpaper;
+    }
+    /** Do not modify unless holding mService.mWindowMap or this and mAnimToLayout in that order */
+    final AnimatorToLayoutParams mAnimToLayout = new AnimatorToLayoutParams();
+
+    WindowAnimator(final WindowManagerService service) {
         mService = service;
-        mContext = context;
-        mPolicy = policy;
+        mContext = service.mContext;
+        mPolicy = service.mPolicy;
+
+        mAnimationRunnable = new Runnable() {
+            @Override
+            public void run() {
+                // TODO(cmautner): When full isolation is achieved for animation, the first lock
+                // goes away and only the WindowAnimator.this remains.
+                synchronized(mService.mWindowMap) {
+                    synchronized(WindowAnimator.this) {
+                        copyLayoutToAnimParamsLocked();
+                        animateLocked();
+                    }
+                }
+            }
+        };
+
+        mWindowAnimationBackgroundSurface = new DimSurface(mService.mFxSession);
+        mDimAnimator = new DimAnimator(mService.mFxSession);
+    }
+
+    /** Locked on mAnimToLayout */
+    void updateAnimToLayoutLocked() {
+        final AnimatorToLayoutParams animToLayout = mAnimToLayout;
+        synchronized (animToLayout) {
+            animToLayout.mBulkUpdateParams = mBulkUpdateParams;
+            animToLayout.mPendingLayoutChanges = mPendingLayoutChanges;
+            animToLayout.mWindowDetachedWallpaper = mWindowDetachedWallpaper;
+
+            if (!animToLayout.mUpdateQueued) {
+                animToLayout.mUpdateQueued = true;
+                mService.mH.sendMessage(mService.mH.obtainMessage(UPDATE_ANIM_PARAMETERS));
+            }
+        }
+    }
+
+    /** Copy all WindowManagerService params into local params here. Locked on 'this'. */
+    private void copyLayoutToAnimParamsLocked() {
+        final LayoutToAnimatorParams layoutToAnim = mService.mLayoutToAnim;
+        synchronized(layoutToAnim) {
+            layoutToAnim.mAnimationScheduled = false;
+
+            if (!layoutToAnim.mParamsModified) {
+                return;
+            }
+            layoutToAnim.mParamsModified = false;
+
+            if ((layoutToAnim.mChanges & LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED) != 0) {
+                layoutToAnim.mChanges &= ~LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED;
+                mWallpaperTokens = new ArrayList<WindowToken>(layoutToAnim.mWallpaperTokens);
+            }
+
+            mWinAnimators = new ArrayList<WindowStateAnimator>(layoutToAnim.mWinAnimators);
+            mWallpaperTarget = layoutToAnim.mWallpaperTarget;
+            mWpAppAnimator = mWallpaperTarget == null
+                    ? null : mWallpaperTarget.mAppToken == null
+                            ? null : mWallpaperTarget.mAppToken.mAppAnimator;
+            mLowerWallpaperTarget = layoutToAnim.mLowerWallpaperTarget;
+            mUpperWallpaperTarget = layoutToAnim.mUpperWallpaperTarget;
+
+            // Set the new DimAnimator params.
+            DimAnimator.Parameters dimParams = layoutToAnim.mDimParams;
+            if (dimParams == null) {
+                mDimParams = dimParams;
+            } else {
+                final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator;
+
+                // Only set dim params on the highest dimmed layer.
+                final WindowStateAnimator existingDimWinAnimator = mDimParams == null
+                        ? null : mDimParams.mDimWinAnimator;
+                // Don't turn on for an unshown surface, or for any layer but the highest dimmed one.
+                if (newWinAnimator.mSurfaceShown &&
+                        (existingDimWinAnimator == null || !existingDimWinAnimator.mSurfaceShown
+                        || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
+                    mDimParams = dimParams;
+                }
+            }
+
+            mAppAnimators.clear();
+            final int N = layoutToAnim.mAppWindowAnimParams.size();
+            for (int i = 0; i < N; i++) {
+                final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i);
+                AppWindowAnimator appAnimator = params.mAppAnimator;
+                appAnimator.mAllAppWinAnimators =
+                        new ArrayList<WindowStateAnimator>(params.mWinAnimators);
+                mAppAnimators.add(appAnimator);
+            }
+        }
     }
 
     void hideWallpapersLocked(final WindowState w) {
-        if ((mService.mWallpaperTarget == w && mService.mLowerWallpaperTarget == null)
-                || mService.mWallpaperTarget == null) {
-            for (final WindowToken token : mService.mWallpaperTokens) {
-                for (final WindowState wallpaper : token.windows) {
+        if ((mWallpaperTarget == w && mLowerWallpaperTarget == null) || mWallpaperTarget == null) {
+            final int numTokens = mWallpaperTokens.size();
+            for (int i = numTokens - 1; i >= 0; i--) {
+                final WindowToken token = mWallpaperTokens.get(i);
+                final int numWindows = token.windows.size();
+                for (int j = numWindows - 1; j >= 0; j--) {
+                    final WindowState wallpaper = token.windows.get(j);
                     final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
                     if (!winAnimator.mLastHidden) {
                         winAnimator.hide();
@@ -108,51 +214,11 @@
         }
     }
 
-    private void testWallpaperAndBackgroundLocked() {
-        if (mWindowDetachedWallpaper != mDetachedWallpaper) {
-            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
-                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
-                    + " to " + mDetachedWallpaper);
-            mWindowDetachedWallpaper = mDetachedWallpaper;
-            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
-        }
-
-        if (mWindowAnimationBackgroundColor != 0) {
-            // If the window that wants black is the current wallpaper
-            // target, then the black goes *below* the wallpaper so we
-            // don't cause the wallpaper to suddenly disappear.
-            WindowState target = mWindowAnimationBackground;
-            if (mService.mWallpaperTarget == target
-                    || mService.mLowerWallpaperTarget == target
-                    || mService.mUpperWallpaperTarget == target) {
-                final int N = mService.mWindows.size();
-                for (int i = 0; i < N; i++) {
-                    WindowState w = mService.mWindows.get(i);
-                    if (w.mIsWallpaper) {
-                        target = w;
-                        break;
-                    }
-                }
-            }
-            if (mWindowAnimationBackgroundSurface == null) {
-                mWindowAnimationBackgroundSurface = new DimSurface(mService.mFxSession);
-            }
-            final int dw = mDw;
-            final int dh = mDh;
-            mWindowAnimationBackgroundSurface.show(dw, dh,
-                    target.mWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM,
-                    mWindowAnimationBackgroundColor);
-        } else if (mWindowAnimationBackgroundSurface != null) {
-            mWindowAnimationBackgroundSurface.hide();
-        }
-    }
-
     private void updateWindowsAppsAndRotationAnimationsLocked() {
-        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
         int i;
-        final int NAT = appTokens.size();
+        final int NAT = mAppAnimators.size();
         for (i=0; i<NAT; i++) {
-            final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
+            final AppWindowAnimator appAnimator = mAppAnimators.get(i);
             final boolean wasAnimating = appAnimator.animation != null
                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
             if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
@@ -199,15 +265,22 @@
         }
     }
 
-    private void updateWindowsAndWallpaperLocked() {
+    private void updateWindowsLocked() {
         ++mAnimTransactionSequence;
 
         ArrayList<WindowStateAnimator> unForceHiding = null;
         boolean wallpaperInUnForceHiding = false;
 
-        for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mService.mWindows.get(i);
-            WindowStateAnimator winAnimator = win.mWinAnimator;
+        // forceHiding states.
+        final int KEYGUARD_NOT_SHOWN     = 0;
+        final int KEYGUARD_ANIMATING_IN  = 1;
+        final int KEYGUARD_SHOWN         = 2;
+        final int KEYGUARD_ANIMATING_OUT = 3;
+        int forceHiding = KEYGUARD_NOT_SHOWN;
+
+        for (int i = mWinAnimators.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = mWinAnimators.get(i);
+            WindowState win = winAnimator.mWin;
             final int flags = winAnimator.mAttrFlags;
 
             if (winAnimator.mSurface != null) {
@@ -219,51 +292,7 @@
                             ", nowAnimating=" + nowAnimating);
                 }
 
-                // If this window is animating, make a note that we have
-                // an animating window and take care of a request to run
-                // a detached wallpaper animation.
-                if (nowAnimating) {
-                    if (winAnimator.mAnimation != null) {
-                        if ((flags & FLAG_SHOW_WALLPAPER) != 0
-                                && winAnimator.mAnimation.getDetachWallpaper()) {
-                            mDetachedWallpaper = win;
-                        }
-                        final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
-                        if (backgroundColor != 0) {
-                            if (mWindowAnimationBackground == null
-                                    || (winAnimator.mAnimLayer <
-                                            mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
-                                mWindowAnimationBackground = win;
-                                mWindowAnimationBackgroundColor = backgroundColor;
-                            }
-                        }
-                    }
-                    mAnimating = true;
-                }
-
-                // If this window's app token is running a detached wallpaper
-                // animation, make a note so we can ensure the wallpaper is
-                // displayed behind it.
-                final AppWindowAnimator appAnimator =
-                        win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
-                if (appAnimator != null && appAnimator.animation != null
-                        && appAnimator.animating) {
-                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
-                            && appAnimator.animation.getDetachWallpaper()) {
-                        mDetachedWallpaper = win;
-                    }
-                    final int backgroundColor = appAnimator.animation.getBackgroundColor();
-                    if (backgroundColor != 0) {
-                        if (mWindowAnimationBackground == null
-                                || (winAnimator.mAnimLayer <
-                                        mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
-                            mWindowAnimationBackground = win;
-                            mWindowAnimationBackgroundColor = backgroundColor;
-                        }
-                    }
-                }
-
-                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
+                if (wasAnimating && !winAnimator.mAnimating && mWallpaperTarget == win) {
                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                     mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -288,16 +317,16 @@
                     if (win.isReadyForDisplay()) {
                         if (nowAnimating) {
                             if (winAnimator.mAnimationIsEntrance) {
-                                mForceHiding = KEYGUARD_ANIMATING_IN;
+                                forceHiding = KEYGUARD_ANIMATING_IN;
                             } else {
-                                mForceHiding = KEYGUARD_ANIMATING_OUT;
+                                forceHiding = KEYGUARD_ANIMATING_OUT;
                             }
                         } else {
-                            mForceHiding = KEYGUARD_SHOWN;
+                            forceHiding = KEYGUARD_SHOWN;
                         }
                     }
                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
-                            "Force hide " + mForceHiding
+                            "Force hide " + forceHiding
                             + " hasSurface=" + win.mHasSurface
                             + " policyVis=" + win.mPolicyVisibility
                             + " destroying=" + win.mDestroying
@@ -309,9 +338,9 @@
                     final boolean hideWhenLocked =
                             (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
                     final boolean changed;
-                    if (((mForceHiding == KEYGUARD_ANIMATING_IN)
+                    if (((forceHiding == KEYGUARD_ANIMATING_IN)
                                 && (!winAnimator.isAnimating() || hideWhenLocked))
-                            || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
+                            || ((forceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
                         changed = win.hideLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
                                 "Now policy hidden: " + win);
@@ -326,7 +355,7 @@
                                     unForceHiding = new ArrayList<WindowStateAnimator>();
                                 }
                                 unForceHiding.add(winAnimator);
-                                if ((win.mAttrs.flags&WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                                if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
                                     wallpaperInUnForceHiding = true;
                                 }
                             }
@@ -338,7 +367,7 @@
                             }
                         }
                     }
-                    if (changed && (flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                    if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                         mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -361,8 +390,7 @@
                     }
                 }
             }
-            final AppWindowAnimator appAnimator =
-                    atoken == null ? null : atoken.mAppAnimator;
+            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
             if (appAnimator != null && appAnimator.thumbnail != null) {
                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
@@ -388,21 +416,112 @@
         }
     }
 
+    private void updateWallpaperLocked() {
+        WindowStateAnimator windowAnimationBackground = null;
+        int windowAnimationBackgroundColor = 0;
+        WindowState detachedWallpaper = null;
+
+        for (int i = mWinAnimators.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = mWinAnimators.get(i);
+            if (winAnimator.mSurface == null) {
+                continue;
+            }
+
+            final int flags = winAnimator.mAttrFlags;
+            final WindowState win = winAnimator.mWin;
+
+            // If this window is animating, make a note that we have
+            // an animating window and take care of a request to run
+            // a detached wallpaper animation.
+            if (winAnimator.mAnimating) {
+                if (winAnimator.mAnimation != null) {
+                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
+                            && winAnimator.mAnimation.getDetachWallpaper()) {
+                        detachedWallpaper = win;
+                    }
+                    final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
+                    if (backgroundColor != 0) {
+                        if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
+                                windowAnimationBackground.mAnimLayer)) {
+                            windowAnimationBackground = winAnimator;
+                            windowAnimationBackgroundColor = backgroundColor;
+                        }
+                    }
+                }
+                mAnimating = true;
+            }
+
+            // If this window's app token is running a detached wallpaper
+            // animation, make a note so we can ensure the wallpaper is
+            // displayed behind it.
+            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
+            if (appAnimator != null && appAnimator.animation != null
+                    && appAnimator.animating) {
+                if ((flags & FLAG_SHOW_WALLPAPER) != 0
+                        && appAnimator.animation.getDetachWallpaper()) {
+                    detachedWallpaper = win;
+                }
+
+                final int backgroundColor = appAnimator.animation.getBackgroundColor();
+                if (backgroundColor != 0) {
+                    if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
+                            windowAnimationBackground.mAnimLayer)) {
+                        windowAnimationBackground = winAnimator;
+                        windowAnimationBackgroundColor = backgroundColor;
+                    }
+                }
+            }
+        } // end forall windows
+
+        if (mWindowDetachedWallpaper != detachedWallpaper) {
+            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
+                    + " to " + detachedWallpaper);
+            mWindowDetachedWallpaper = detachedWallpaper;
+            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+        }
+
+        if (windowAnimationBackgroundColor != 0) {
+            // If the window that wants black is the current wallpaper
+            // target, then the black goes *below* the wallpaper so we
+            // don't cause the wallpaper to suddenly disappear.
+            int animLayer = windowAnimationBackground.mAnimLayer;
+            WindowState win = windowAnimationBackground.mWin;
+            if (windowAnimationBackground != null && mWallpaperTarget == win
+                    || mLowerWallpaperTarget == win || mUpperWallpaperTarget == win) {
+                final int N = mWinAnimators.size();
+                for (int i = 0; i < N; i++) {
+                    WindowStateAnimator winAnimator = mWinAnimators.get(i);
+                    if (winAnimator.mIsWallpaper) {
+                        animLayer = winAnimator.mAnimLayer;
+                        break;
+                    }
+                }
+            }
+
+            mWindowAnimationBackgroundSurface.show(mDw, mDh,
+                    animLayer - WindowManagerService.LAYER_OFFSET_DIM,
+                    windowAnimationBackgroundColor);
+        } else {
+            mWindowAnimationBackgroundSurface.hide();
+        }
+    }
+
     private void testTokenMayBeDrawnLocked() {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
-        final int NT = appTokens.size();
+        final int NT = mAppAnimators.size();
         for (int i=0; i<NT; i++) {
-            AppWindowToken wtoken = appTokens.get(i);
+            AppWindowAnimator appAnimator = mAppAnimators.get(i);
+            AppWindowToken wtoken = appAnimator.mAppToken;
             final boolean allDrawn = wtoken.allDrawn;
-            if (allDrawn != wtoken.mAppAnimator.allDrawn) {
-                wtoken.mAppAnimator.allDrawn = allDrawn;
+            if (allDrawn != appAnimator.allDrawn) {
+                appAnimator.allDrawn = allDrawn;
                 if (allDrawn) {
                     // The token has now changed state to having all
                     // windows shown...  what to do, what to do?
-                    if (wtoken.mAppAnimator.freezingScreen) {
-                        wtoken.mAppAnimator.showAllWindowsLocked();
+                    if (appAnimator.freezingScreen) {
+                        appAnimator.showAllWindowsLocked();
                         mService.unsetAppFreezingScreenLocked(wtoken, false, true);
                         if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
                                 "Setting mOrientationChangeComplete=true because wtoken "
@@ -419,7 +538,7 @@
 
                         // We can now show all of the drawn windows!
                         if (!mService.mOpeningApps.contains(wtoken)) {
-                            mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+                            mAnimating |= appAnimator.showAllWindowsLocked();
                         }
                     }
                 }
@@ -428,12 +547,9 @@
     }
 
     private void performAnimationsLocked() {
-        mForceHiding = KEYGUARD_NOT_SHOWN;
-        mDetachedWallpaper = null;
-        mWindowAnimationBackground = null;
-        mWindowAnimationBackgroundColor = 0;
+        updateWindowsLocked();
+        updateWallpaperLocked();
 
-        updateWindowsAndWallpaperLocked();
         if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
             mPendingActions |= WALLPAPER_ACTION_PENDING;
         }
@@ -441,10 +557,12 @@
         testTokenMayBeDrawnLocked();
     }
 
-    synchronized void animate() {
+    // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
+    /** Locked on mService.mWindowMap and this. */
+    private void animateLocked() {
         mPendingLayoutChanges = 0;
         mCurrentTime = SystemClock.uptimeMillis();
-        mBulkUpdateParams = 0;
+        mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
         boolean wasAnimating = mAnimating;
         mAnimating = false;
         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
@@ -458,7 +576,6 @@
         try {
             updateWindowsAppsAndRotationAnimationsLocked();
             performAnimationsLocked();
-            testWallpaperAndBackgroundLocked();
 
             // THIRD LOOP: Update the surfaces of all windows.
 
@@ -497,10 +614,14 @@
             Surface.closeTransaction();
         }
 
-        mService.bulkSetParameters(mBulkUpdateParams, mPendingLayoutChanges);
+        if (mBulkUpdateParams != 0 || mPendingLayoutChanges != 0) {
+            updateAnimToLayoutLocked();
+        }
 
         if (mAnimating) {
-            mService.scheduleAnimationLocked();
+            synchronized (mService.mLayoutToAnim) {
+                mService.scheduleAnimationLocked();
+            }
         } else if (wasAnimating) {
             mService.requestTraversalLocked();
         }
@@ -524,28 +645,6 @@
         mInnerDh = appHeight;
     }
 
-    void startDimming(final WindowStateAnimator winAnimator, final float target,
-                      final int width, final int height) {
-        if (mDimAnimator == null) {
-            mDimAnimator = new DimAnimator(mService.mFxSession);
-        }
-        // Only set dim params on the highest dimmed layer.
-        final WindowStateAnimator dimWinAnimator = mDimParams == null
-                ? null : mDimParams.mDimWinAnimator;
-        // Don't turn on for an unshown surface, or for any layer but the highest dimmed one.
-        if (winAnimator.mSurfaceShown &&
-                (dimWinAnimator == null || !dimWinAnimator.mSurfaceShown
-                || dimWinAnimator.mAnimLayer < winAnimator.mAnimLayer)) {
-            mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS,
-                    new DimAnimator.Parameters(winAnimator, width, height, target)));
-        }
-    }
-
-    // TODO(cmautner): Move into Handler
-    void stopDimming() {
-        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
-    }
-
     boolean isDimming() {
         return mDimParams != null;
     }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7011343..d0456ee 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -31,6 +31,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import com.android.internal.app.IBatteryStats;
@@ -42,12 +43,11 @@
 import com.android.internal.view.WindowManagerPolicyThread;
 import com.android.server.AttributeCache;
 import com.android.server.EventLogTags;
-import com.android.server.PowerManagerService;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
-import com.android.server.input.InputFilter;
 import com.android.server.input.InputManagerService;
-import com.android.server.pm.ShutdownThread;
+import com.android.server.power.PowerManagerService;
+import com.android.server.power.ShutdownThread;
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
@@ -69,6 +69,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.BatteryStats;
 import android.os.Binder;
@@ -96,7 +97,7 @@
 import android.util.EventLog;
 import android.util.FloatMath;
 import android.util.Log;
-import android.util.LogPrinter;
+//import android.util.LogPrinter;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseIntArray;
@@ -105,6 +106,7 @@
 import android.view.Display;
 import android.view.Gravity;
 import android.view.IApplicationToken;
+import android.view.IInputFilter;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
 import android.view.IWindow;
@@ -119,6 +121,7 @@
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.View;
+import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
@@ -131,6 +134,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.ScaleAnimation;
+import android.view.animation.Transformation;
 
 import java.io.BufferedWriter;
 import java.io.DataInputStream;
@@ -496,6 +500,7 @@
 
     final Rect mSystemDecorRect = new Rect();
     int mSystemDecorLayer = 0;
+    final Rect mScreenRect = new Rect();
 
     int mPendingLayoutChanges = 0;
     boolean mLayoutNeeded = true;
@@ -512,9 +517,9 @@
 
     // State while inside of layoutAndPlaceSurfacesLocked().
     boolean mFocusMayChange;
-    
+
     Configuration mCurConfiguration = new Configuration();
-    
+
     // This is held as long as we have the screen frozen, to give us time to
     // perform a rotation animation when turning off shows the lock screen which
     // changes the orientation.
@@ -583,10 +588,10 @@
     WindowState mWallpaperTarget = null;
     // If non-null, we are in the middle of animating from one wallpaper target
     // to another, and this is the lower one in Z-order.
-    WindowState mLowerWallpaperTarget = null;
+    private WindowState mLowerWallpaperTarget = null;
     // If non-null, we are in the middle of animating from one wallpaper target
     // to another, and this is the higher one in Z-order.
-    WindowState mUpperWallpaperTarget = null;
+    private WindowState mUpperWallpaperTarget = null;
     int mWallpaperAnimLayerAdjustment;
     float mLastWallpaperX = -1;
     float mLastWallpaperY = -1;
@@ -626,7 +631,7 @@
         static final int SET_UPDATE_ROTATION                = 1 << 0;
         static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
         static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
-        static final int CLEAR_ORIENTATION_CHANGE_COMPLETE  = 1 << 3;
+        static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
         static final int SET_TURN_ON_SCREEN                 = 1 << 4;
 
         boolean mWallpaperForceHidingChanged = false;
@@ -641,7 +646,45 @@
         private float mButtonBrightness = -1;
         private boolean mUpdateRotation = false;
     }
-    LayoutFields mInnerFields = new LayoutFields();
+    final LayoutFields mInnerFields = new LayoutFields();
+
+    static class AppWindowAnimParams {
+        AppWindowAnimator mAppAnimator;
+        ArrayList<WindowStateAnimator> mWinAnimators;
+
+        public AppWindowAnimParams(final AppWindowAnimator appAnimator) {
+            mAppAnimator = appAnimator;
+
+            final AppWindowToken wtoken = appAnimator.mAppToken;
+            mWinAnimators = new ArrayList<WindowStateAnimator>();
+            final int N = wtoken.allAppWindows.size();
+            for (int i = 0; i < N; i++) {
+                mWinAnimators.add(wtoken.allAppWindows.get(i).mWinAnimator);
+            }
+        }
+    }
+
+    static class LayoutToAnimatorParams {
+        boolean mParamsModified;
+
+        static final long WALLPAPER_TOKENS_CHANGED = 1 << 0;
+        long mChanges;
+
+        boolean mAnimationScheduled;
+        ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
+        WindowState mWallpaperTarget;
+        WindowState mLowerWallpaperTarget;
+        WindowState mUpperWallpaperTarget;
+        DimAnimator.Parameters mDimParams;
+        ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+        ArrayList<AppWindowAnimParams> mAppWindowAnimParams = new ArrayList<AppWindowAnimParams>();
+    }
+    /** Params from WindowManagerService to WindowAnimator. Do not modify or read without first
+     * locking on either mWindowMap or mAnimator and then on mLayoutToAnim */
+    final LayoutToAnimatorParams mLayoutToAnim = new LayoutToAnimatorParams();
+
+    /** The lowest wallpaper target with a detached wallpaper animation on it. */
+    WindowState mWindowDetachedWallpaper = null;
 
     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
@@ -650,33 +693,6 @@
     /** Only do a maximum of 6 repeated layouts. After that quit */
     private int mLayoutRepeatCount;
 
-    private final class AnimationRunnable implements Runnable {
-        @Override
-        public void run() {
-            synchronized(mWindowMap) {
-                mAnimationScheduled = false;
-                // Update animations of all applications, including those
-                // associated with exiting/removed apps
-                synchronized (mAnimator) {
-                    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmAnimate");
-                    final ArrayList<WindowStateAnimator> winAnimators = mAnimator.mWinAnimators;
-                    winAnimators.clear();
-                    final int N = mWindows.size();
-                    for (int i = 0; i < N; i++) {
-                        final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator;
-                        if (winAnimator.mSurface != null) {
-                            winAnimators.add(winAnimator);
-                        }
-                    }
-                    mAnimator.animate();
-                    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
-                }
-            }
-        }
-    }
-    final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
-    boolean mAnimationScheduled;
-    
     final WindowAnimator mAnimator;
 
     final class DragInputEventReceiver extends InputEventReceiver {
@@ -850,13 +866,16 @@
         public void run() {
             Looper.prepare();
             WindowManagerPolicyThread.set(this, Looper.myLooper());
-            
+
             //Looper.myLooper().setMessageLogging(new LogPrinter(
             //        Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
             android.os.Process.setThreadPriority(
                     android.os.Process.THREAD_PRIORITY_FOREGROUND);
             android.os.Process.setCanSelfBackground(false);
             mPolicy.init(mContext, mService, mService, mPM);
+            mService.mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
+                    * TYPE_LAYER_MULTIPLIER
+                    + TYPE_LAYER_OFFSET;
 
             synchronized (this) {
                 mRunning = true;
@@ -910,7 +929,8 @@
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
         mInputManager = new InputManagerService(context, mInputMonitor);
-        mAnimator = new WindowAnimator(this, context, mPolicy);
+        mFxSession = new SurfaceSession();
+        mAnimator = new WindowAnimator(this);
 
         PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
         thr.start();
@@ -928,7 +948,6 @@
 
         // Add ourself to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
-        mFxSession = new SurfaceSession();
 
         Surface.openTransaction();
         createWatermark();
@@ -1592,9 +1611,9 @@
                     Slog.v(TAG, "List with no IM target:");
                     logWindowList("  ");
                 }
-                if (DN > 0) moveInputMethodDialogsLocked(-1);;
+                if (DN > 0) moveInputMethodDialogsLocked(-1);
             } else {
-                moveInputMethodDialogsLocked(-1);;
+                moveInputMethodDialogsLocked(-1);
             }
 
         }
@@ -1656,7 +1675,7 @@
                 continue;
             }
             topCurW = null;
-            if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
+            if (w != mWindowDetachedWallpaper && w.mAppToken != null) {
                 // If this window's app token is hidden and not animating,
                 // it is of no interest to us.
                 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
@@ -1682,7 +1701,7 @@
                     continue;
                 }
                 break;
-            } else if (w == mAnimator.mWindowDetachedWallpaper) {
+            } else if (w == mWindowDetachedWallpaper) {
                 windowDetachedI = i;
             }
         }
@@ -1760,7 +1779,7 @@
                             mWallpaperTarget = oldW;
                             foundW = oldW;
                             foundI = oldI;
-                        } 
+                        }
                         // Now set the upper and lower wallpaper targets
                         // correctly, and make sure that we are positioning
                         // the wallpaper below the lower.
@@ -2040,11 +2059,6 @@
         }
     }
 
-    // TODO(cmautner):  Move to WindowAnimator.
-    void setWallpaperOffset(final WindowStateAnimator winAnimator, final int left, final int top) {
-        mH.sendMessage(mH.obtainMessage(H.SET_WALLPAPER_OFFSET, left, top, winAnimator));
-    }
-
     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
         final int dw = mAppDisplayWidth;
         final int dh = mAppDisplayHeight;
@@ -2079,19 +2093,8 @@
                     // TODO(cmautner): Don't move this from here, just lock the WindowAnimator.
                     if (winAnimator.mSurfaceX != wallpaper.mShownFrame.left
                             || winAnimator.mSurfaceY != wallpaper.mShownFrame.top) {
-                        Surface.openTransaction();
-                        try {
-                            if (SHOW_TRANSACTIONS) logSurface(wallpaper,
-                                    "POS " + wallpaper.mShownFrame.left
-                                    + ", " + wallpaper.mShownFrame.top, null);
-                            setWallpaperOffset(winAnimator, (int) wallpaper.mShownFrame.left,
+                        winAnimator.setWallpaperOffset((int) wallpaper.mShownFrame.left,
                                 (int) wallpaper.mShownFrame.top);
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Error positioning surface of " + wallpaper
-                                    + " pos=(" + wallpaper.mShownFrame.left
-                                    + "," + wallpaper.mShownFrame.top + ")", e);
-                        }
-                        Surface.closeTransaction();
                     }
                     // We only want to be synchronous with one wallpaper.
                     sync = false;
@@ -2146,7 +2149,7 @@
             }
         }
     }
-    
+
     public int addWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int viewVisibility,
             Rect outContentInsets, InputChannel outInputChannel) {
@@ -2265,14 +2268,14 @@
             if (res != WindowManagerImpl.ADD_OKAY) {
                 return res;
             }
-            
+
             if (outInputChannel != null && (attrs.inputFeatures
                     & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                 String name = win.makeInputChannelName();
                 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
                 win.setInputChannel(inputChannels[0]);
                 inputChannels[1].transferTo(outInputChannel);
-                
+
                 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
             }
 
@@ -2357,7 +2360,7 @@
             if (localLOGV) Slog.v(
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
-            
+
             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                 reportNewConfig = true;
             }
@@ -2550,7 +2553,7 @@
                 win.mAppToken.updateReportedVisibilityLocked();
             }
         }
-        
+
         mInputMonitor.updateInputWindowsLw(true /*force*/);
     }
 
@@ -2683,6 +2686,29 @@
         return null;
     }
 
+    public void setUniverseTransformLocked(WindowState window, float alpha,
+            float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
+        Transformation transform = window.mWinAnimator.mUniverseTransform;
+        transform.setAlpha(alpha);
+        Matrix matrix = transform.getMatrix();
+        matrix.getValues(mTmpFloats);
+        mTmpFloats[Matrix.MTRANS_X] = offx;
+        mTmpFloats[Matrix.MTRANS_Y] = offy;
+        mTmpFloats[Matrix.MSCALE_X] = dsdx;
+        mTmpFloats[Matrix.MSKEW_Y] = dtdx;
+        mTmpFloats[Matrix.MSKEW_X] = dsdy;
+        mTmpFloats[Matrix.MSCALE_Y] = dtdy;
+        matrix.setValues(mTmpFloats);
+        final RectF dispRect = new RectF(0, 0, mCurDisplayWidth, mCurDisplayHeight);
+        matrix.mapRect(dispRect);
+        window.mGivenTouchableRegion.set(0, 0, mCurDisplayWidth, mCurDisplayHeight);
+        window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
+                (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
+        window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+        mLayoutNeeded = true;
+        performLayoutAndPlaceSurfacesLocked();
+    }
+
     public int relayoutWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int requestedWidth,
             int requestedHeight, int viewVisibility, int flags,
@@ -2848,7 +2874,7 @@
                     }
                 } catch (Exception e) {
                     mInputMonitor.updateInputWindowsLw(true /*force*/);
-                    
+
                     Slog.w(TAG, "Exception thrown when creating surface for client "
                              + client + " (" + win.mAttrs.getTitle() + ")",
                              e);
@@ -3043,6 +3069,10 @@
     }
 
     public float getWindowCompatibilityScale(IBinder windowToken) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getWindowCompatibilityScale()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
         synchronized (mWindowMap) {
             WindowState windowState = mWindowMap.get(windowToken);
             return (windowState != null) ? windowState.mGlobalScale : 1.0f;
@@ -3128,12 +3158,11 @@
             a.setDetachWallpaper(true);
             a.setDuration(duration);
             return a;
-        } else {
-            // For normal animations, the exiting element just holds in place.
-            Animation a = new AlphaAnimation(1, 1);
-            a.setDuration(duration);
-            return a;
         }
+        // For normal animations, the exiting element just holds in place.
+        Animation a = new AlphaAnimation(1, 1);
+        a.setDuration(duration);
+        return a;
     }
 
     /**
@@ -3440,7 +3469,7 @@
         Slog.w(TAG, msg);
         return false;
     }
-    
+
     boolean okToDisplay() {
         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
     }
@@ -3470,10 +3499,12 @@
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
+                updateLayoutToAnimWallpaperTokens();
             }
         }
     }
 
+    @Override
     public void removeWindowToken(IBinder token) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "removeWindowToken()")) {
@@ -3515,6 +3546,7 @@
                         mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
                         mWallpaperTokens.remove(wtoken);
+                        updateLayoutToAnimWallpaperTokens();
                     }
                 }
 
@@ -3591,6 +3623,7 @@
         }
     }
 
+    @Override
     public void setAppGroupId(IBinder token, int groupId) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppGroupId()")) {
@@ -3633,9 +3666,9 @@
             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
                 continue;
-            } else {
-                return (mLastWindowForcedOrientation=req);
             }
+
+            return (mLastWindowForcedOrientation=req);
         }
         return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
     }
@@ -3685,7 +3718,7 @@
                 haveGroup = true;
                 curGroup = wtoken.groupId;
                 lastOrientation = wtoken.requestedOrientation;
-            } 
+            }
 
             int or = wtoken.requestedOrientation;
             // If this application is fullscreen, and didn't explicitly say
@@ -3712,6 +3745,7 @@
         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     }
 
+    @Override
     public Configuration updateOrientationFromAppTokens(
             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3810,6 +3844,7 @@
         return req;
     }
 
+    @Override
     public void setNewConfiguration(Configuration config) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setNewConfiguration()")) {
@@ -3822,7 +3857,8 @@
             performLayoutAndPlaceSurfacesLocked();
         }
     }
-    
+
+    @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppOrientation()")) {
@@ -5158,7 +5194,10 @@
         ShutdownThread.rebootSafeMode(mContext, true);
     }
 
-    public void setInputFilter(InputFilter filter) {
+    public void setInputFilter(IInputFilter filter) {
+        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
+            throw new SecurityException("Requires FILTER_EVENTS permission");
+        }
         mInputManager.setInputFilter(filter);
     }
 
@@ -5778,7 +5817,7 @@
                 if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
                         mCurDisplayWidth, mCurDisplayHeight)) {
-                    scheduleAnimationLocked();
+                    updateLayoutToAnimationLocked();
                 }
             }
             Surface.setOrientation(0, rotation);
@@ -5875,7 +5914,7 @@
                     case Surface.ROTATION_180:
                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                     case Surface.ROTATION_270:
-                        return Gravity.LEFT | Gravity.BOTTOM;
+                        return Gravity.START | Gravity.BOTTOM;
                 }
             } else {
                 // On devices with a natural orientation of landscape
@@ -5886,7 +5925,7 @@
                     case Surface.ROTATION_90:
                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                     case Surface.ROTATION_180:
-                        return Gravity.LEFT | Gravity.BOTTOM;
+                        return Gravity.START | Gravity.BOTTOM;
                     case Surface.ROTATION_270:
                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                 }
@@ -6720,8 +6759,11 @@
         }
     }
 
-    // TODO: Put this on the IWindowManagerService and guard with a permission.
-    public IBinder getFocusedWindowClientToken() {
+    public IBinder getFocusedWindowToken() {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getFocusedWindowToken()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
         synchronized (mWindowMap) {
             WindowState windowState = getFocusedWindowLocked();
             if (windowState != null) {
@@ -6731,8 +6773,11 @@
         }
     }
 
-    // TODO: This is a workaround - remove when 6623031 is fixed.
     public boolean getWindowFrame(IBinder token, Rect outBounds) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getWindowFrame()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
         synchronized (mWindowMap) {
             WindowState windowState = mWindowMap.get(token);
             if (windowState != null) {
@@ -6877,15 +6922,13 @@
         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
         public static final int BOOT_TIMEOUT = 23;
         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
-        public static final int BULK_UPDATE_PARAMETERS = 25;
+        public static final int UPDATE_ANIM_PARAMETERS = 25;
         public static final int SHOW_STRICT_MODE_VIOLATION = 26;
         public static final int DO_ANIMATION_CALLBACK = 27;
 
         public static final int ANIMATOR_WHAT_OFFSET = 100000;
         public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
-        public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2;
-        public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3;
-        public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 4;
+        public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2;
 
         private Session mLastReportedHold;
 
@@ -7191,18 +7234,22 @@
                 }
 
                 case FORCE_GC: {
-                    synchronized(mWindowMap) {
-                        if (mAnimationScheduled) {
-                            // If we are animating, don't do the gc now but
-                            // delay a bit so we don't interrupt the animation.
-                            mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
-                                    2000);
-                            return;
-                        }
-                        // If we are currently rotating the display, it will
-                        // schedule a new message when done.
-                        if (mDisplayFrozen) {
-                            return;
+                    synchronized (mWindowMap) {
+                        synchronized (mAnimator) {
+                            // Since we're holding both mWindowMap and mAnimator we don't need to
+                            // hold mAnimator.mLayoutToAnim.
+                            if (mAnimator.mAnimating || mLayoutToAnim.mAnimationScheduled) {
+                                // If we are animating, don't do the gc now but
+                                // delay a bit so we don't interrupt the animation.
+                                mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
+                                        2000);
+                                return;
+                            }
+                            // If we are currently rotating the display, it will
+                            // schedule a new message when done.
+                            if (mDisplayFrozen) {
+                                return;
+                            }
                         }
                     }
                     Runtime.getRuntime().gc();
@@ -7306,42 +7353,10 @@
                     break;
                 }
 
-                case BULK_UPDATE_PARAMETERS: {
+                case UPDATE_ANIM_PARAMETERS: {
                     // Used to send multiple changes from the animation side to the layout side.
                     synchronized (mWindowMap) {
-                        boolean doRequest = false;
-                        // TODO(cmautner): As the number of bits grows, use masks of bit groups to
-                        //  eliminate unnecessary tests.
-                        if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) {
-                            mInnerFields.mUpdateRotation = true;
-                            doRequest = true;
-                        }
-                        if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
-                            mInnerFields.mWallpaperMayChange = true;
-                            doRequest = true;
-                        }
-                        if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
-                            mInnerFields.mWallpaperForceHidingChanged = true;
-                            doRequest = true;
-                        }
-                        if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) {
-                            mInnerFields.mOrientationChangeComplete = false;
-                        } else {
-                            mInnerFields.mOrientationChangeComplete = true;
-                            if (mWindowsFreezingScreen) {
-                                doRequest = true;
-                            }
-                        }
-                        if ((msg.arg1 & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
-                            mTurnOnScreen = true;
-                        }
-
-                        mPendingLayoutChanges |= msg.arg2;
-                        if (mPendingLayoutChanges != 0) {
-                            doRequest = true;
-                        }
-
-                        if (doRequest) {
+                        if (copyAnimToLayoutParamsLocked()) {
                             mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS);
                             performLayoutAndPlaceSurfacesLocked();
                         }
@@ -7363,21 +7378,6 @@
                     break;
                 }
 
-                case SET_WALLPAPER_OFFSET: {
-                    final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
-                    winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
-
-                    scheduleAnimationLocked();
-                    break;
-                }
-
-                case SET_DIM_PARAMETERS: {
-                    mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
-
-                    scheduleAnimationLocked();
-                    break;
-                }
-
                 case CLEAR_PENDING_ACTIONS: {
                     mAnimator.clearPendingActions();
                     break;
@@ -7662,7 +7662,7 @@
     final void rebuildAppWindowListLocked() {
         int NW = mWindows.size();
         int i;
-        int lastWallpaper = -1;
+        int lastBelow = -1;
         int numRemoved = 0;
 
         if (mRebuildTmp.length < NW) {
@@ -7683,17 +7683,19 @@
                 NW--;
                 numRemoved++;
                 continue;
-            } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
-                    && lastWallpaper == i-1) {
-                lastWallpaper = i;
+            } else if (lastBelow == i-1) {
+                if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
+                        || w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
+                    lastBelow = i;
+                }
             }
             i++;
         }
 
-        // The wallpaper window(s) typically live at the bottom of the stack,
-        // so skip them before adding app tokens.
-        lastWallpaper++;
-        i = lastWallpaper;
+        // Keep whatever windows were below the app windows still below,
+        // by skipping them.
+        lastBelow++;
+        i = lastBelow;
 
         // First add all of the exiting app tokens...  these are no longer
         // in the main app list, but still have windows shown.  We put them
@@ -7710,7 +7712,7 @@
             i = reAddAppWindowsLocked(i, mAnimatingAppTokens.get(j));
         }
 
-        i -= lastWallpaper;
+        i -= lastBelow;
         if (i != numRemoved) {
             Slog.w(TAG, "Rebuild removed " + numRemoved
                     + " windows but added " + i);
@@ -7781,7 +7783,7 @@
             }
             if (layerChanged && mAnimator.isDimming(winAnimator)) {
                 // Force an animation pass just to update the mDimAnimator layer.
-                scheduleAnimationLocked();
+                updateLayoutToAnimationLocked();
             }
             if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
                     + winAnimator.mAnimLayer);
@@ -7913,9 +7915,12 @@
             Slog.v(TAG, "performLayout: needed="
                     + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
         }
-        
+
+        WindowStateAnimator universeBackground = null;
+
         mPolicy.beginLayoutLw(dw, dh, mRotation);
         mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect);
+        mScreenRect.set(0, 0, dw, dh);
 
         int seq = mLayoutSeq+1;
         if (seq < 0) seq = 0;
@@ -7956,7 +7961,8 @@
             // if they want.  (We do the normal layout for INVISIBLE
             // windows, since that means "perform layout as normal,
             // just don't display").
-            if (!gone || !win.mHaveFrame || win.mLayoutNeeded) {
+            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
+                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
@@ -7974,6 +7980,16 @@
                     if (topAttached < 0) topAttached = i;
                 }
             }
+            if (win.mViewVisibility == View.VISIBLE
+                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
+                    && universeBackground == null) {
+                universeBackground = win.mWinAnimator;
+            }
+        }
+
+        if (mAnimator.mUniverseBackground  != universeBackground) {
+            mFocusMayChange = true;
+            mAnimator.mUniverseBackground = universeBackground;
         }
 
         // Now perform layout of attached windows, which usually
@@ -8482,8 +8498,7 @@
                         width = innerDw;
                         height = innerDh;
                     }
-                    mAnimator.startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount,
-                            width, height);
+                    startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
                 }
             }
         }
@@ -8660,6 +8675,10 @@
                     winAnimator.setAnimation(a);
                     winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
                     winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+                    try {
+                        w.mClient.moved(w.mFrame.left, w.mFrame.top);
+                    } catch (RemoteException e) {
+                    }
                 }
 
                 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
@@ -8676,7 +8695,7 @@
                             mInnerFields.mWallpaperMayChange = true;
                             mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                             if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("updateWindowsAndWallpaperLocked 1",
+                                debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",
                                     mPendingLayoutChanges);
                             }
                         }
@@ -8690,7 +8709,8 @@
                             + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
                             + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
                     }
-                    if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
+                    if (atoken != null
+                            && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
                         if (atoken.lastTransactionSequence != mTransactionSequence) {
                             atoken.lastTransactionSequence = mTransactionSequence;
                             atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
@@ -8748,7 +8768,7 @@
             }
 
             if (!mInnerFields.mDimming && mAnimator.isDimming()) {
-                mAnimator.stopDimming();
+                stopDimming();
             }
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
@@ -8899,6 +8919,7 @@
                 mExitingTokens.remove(i);
                 if (token.windowType == TYPE_WALLPAPER) {
                     mWallpaperTokens.remove(token);
+                    updateLayoutToAnimWallpaperTokens();
                 }
             }
         }
@@ -8986,7 +9007,7 @@
         // be enabled, because the window obscured flags have changed.
         enableScreenIfNeededLocked();
 
-        scheduleAnimationLocked();
+        updateLayoutToAnimationLocked();
 
         if (DEBUG_WINDOW_TRACE) {
             Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges="
@@ -9063,13 +9084,111 @@
         }
     }
 
+    /** Note that Locked in this case is on mLayoutToAnim */
     void scheduleAnimationLocked() {
-        if (!mAnimationScheduled) {
-            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null);
-            mAnimationScheduled = true;
+        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
+        if (!layoutToAnim.mAnimationScheduled) {
+            layoutToAnim.mAnimationScheduled = true;
+            mChoreographer.postCallback(
+                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
         }
     }
 
+    void updateLayoutToAnimationLocked() {
+        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
+        synchronized (layoutToAnim) {
+            // Copy local params to transfer params.
+            ArrayList<WindowStateAnimator> winAnimators = layoutToAnim.mWinAnimators;
+            winAnimators.clear();
+            int N = mWindows.size();
+            for (int i = 0; i < N; i++) {
+                final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator;
+                if (winAnimator.mSurface != null) {
+                    winAnimators.add(winAnimator);
+                }
+            }
+
+            layoutToAnim.mWallpaperTarget = mWallpaperTarget;
+            layoutToAnim.mLowerWallpaperTarget = mLowerWallpaperTarget;
+            layoutToAnim.mUpperWallpaperTarget = mUpperWallpaperTarget;
+
+            final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams;
+            paramList.clear();
+            N = mAnimatingAppTokens.size();
+            for (int i = 0; i < N; i++) {
+                paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator));
+            }
+
+            layoutToAnim.mParamsModified = true;
+            scheduleAnimationLocked();
+        }
+    }
+
+    void updateLayoutToAnimWallpaperTokens() {
+        synchronized(mLayoutToAnim) {
+            mLayoutToAnim.mWallpaperTokens = new ArrayList<WindowToken>(mWallpaperTokens);
+            mLayoutToAnim.mChanges |= LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED;
+        }
+    }
+
+    void setAnimDimParams(DimAnimator.Parameters params) {
+        synchronized (mLayoutToAnim) {
+            mLayoutToAnim.mDimParams = params;
+            scheduleAnimationLocked();
+        }
+    }
+
+    void startDimming(final WindowStateAnimator winAnimator, final float target,
+                      final int width, final int height) {
+        setAnimDimParams(new DimAnimator.Parameters(winAnimator, width, height, target));
+    }
+
+    void stopDimming() {
+        setAnimDimParams(null);
+    }
+
+    private boolean copyAnimToLayoutParamsLocked() {
+        boolean doRequest = false;
+        final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout;
+        synchronized (animToLayout) {
+            animToLayout.mUpdateQueued = false;
+            final int bulkUpdateParams = animToLayout.mBulkUpdateParams;
+            // TODO(cmautner): As the number of bits grows, use masks of bit groups to
+            //  eliminate unnecessary tests.
+            if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
+                mInnerFields.mUpdateRotation = true;
+                doRequest = true;
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
+                mInnerFields.mWallpaperMayChange = true;
+                doRequest = true;
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+                mInnerFields.mWallpaperForceHidingChanged = true;
+                doRequest = true;
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
+                mInnerFields.mOrientationChangeComplete = false;
+            } else {
+                mInnerFields.mOrientationChangeComplete = true;
+                if (mWindowsFreezingScreen) {
+                    doRequest = true;
+                }
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
+                mTurnOnScreen = true;
+            }
+
+            mPendingLayoutChanges |= animToLayout.mPendingLayoutChanges;
+            if (mPendingLayoutChanges != 0) {
+                doRequest = true;
+            }
+
+            mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper;
+        }
+        return doRequest;
+    }
+
     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
                                            boolean secure) {
         final Surface surface = winAnimator.mSurface;
@@ -9232,6 +9351,11 @@
         WindowState result = null;
         WindowState win;
 
+        if (mAnimator.mUniverseBackground != null
+                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
+            return mAnimator.mUniverseBackground.mWin;
+        }
+
         int nextAppIndex = mAppTokens.size()-1;
         WindowToken nextApp = nextAppIndex >= 0
             ? mAppTokens.get(nextAppIndex) : null;
@@ -9334,12 +9458,6 @@
             mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
                     mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
                     mDisplay.getRotation());
-
-            if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
-                Surface.freezeDisplay(0);
-            }
-        } else {
-            Surface.freezeDisplay(0);
         }
     }
 
@@ -9369,7 +9487,7 @@
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
             if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
                     mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
-                scheduleAnimationLocked();
+                updateLayoutToAnimationLocked();
             } else {
                 mAnimator.mScreenRotationAnimation.kill();
                 mAnimator.mScreenRotationAnimation = null;
@@ -9382,7 +9500,6 @@
             }
             updateRotation = true;
         }
-        Surface.unfreezeDisplay(0);
 
         mInputMonitor.thawInputDispatchingLw();
 
@@ -9847,7 +9964,8 @@
                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
         if (dumpAll) {
             pw.print("  mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString());
-                    pw.print(" mSystemDecorLayer="); pw.println(mSystemDecorLayer);
+                    pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
+                    pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString());
             if (mLastStatusBarVisibility != 0) {
                 pw.print("  mLastStatusBarVisibility=0x");
                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
@@ -10146,9 +10264,4 @@
                     Integer.toHexString(pendingLayoutChanges));
         }
     }
-
-    void bulkSetParameters(final int bulkUpdateParams, int pendingLayoutChanges) {
-        mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams,
-                pendingLayoutChanges));
-    }
 }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index a00e8a5..94fd199 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -317,9 +317,6 @@
             mIsFloatingLayer = mIsImWindow || mIsWallpaper;
         }
 
-        mWinAnimator = new WindowStateAnimator(service, this, mAttachedWindow);
-        mWinAnimator.mAlpha = a.alpha;
-
         WindowState appWin = this;
         while (appWin.mAttachedWindow != null) {
             appWin = appWin.mAttachedWindow;
@@ -335,6 +332,9 @@
         mRootToken = appToken;
         mAppToken = appToken.appWindowToken;
 
+        mWinAnimator = new WindowStateAnimator(this);
+        mWinAnimator.mAlpha = a.alpha;
+
         mRequestedWidth = 0;
         mRequestedHeight = 0;
         mLastRequestedWidth = 0;
@@ -907,7 +907,7 @@
             mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -950,7 +950,7 @@
             }
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -1060,6 +1060,9 @@
             if (mTouchableInsets != 0 || mGivenInsetsPending) {
                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+                Region region = new Region();
+                getTouchableRegion(region);
+                pw.print(prefix); pw.print("touchable region="); pw.println(region);
             }
             pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
         }
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 03e52fe..f08204f 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -3,9 +3,8 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
-import static com.android.server.wm.WindowManagerService.LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN;
 
 import android.content.Context;
@@ -48,13 +47,20 @@
 
     static final String TAG = "WindowStateAnimator";
 
+    // Unchanging local convenience fields.
     final WindowManagerService mService;
     final WindowState mWin;
-    final WindowState mAttachedWindow;
+    final WindowStateAnimator mAttachedWinAnimator;
     final WindowAnimator mAnimator;
+    final AppWindowAnimator mAppAnimator;
     final Session mSession;
     final WindowManagerPolicy mPolicy;
     final Context mContext;
+    final boolean mIsWallpaper;
+
+    // If this is a universe background window, this is the transformation
+    // it is applying to the rest of the universe.
+    final Transformation mUniverseTransform = new Transformation();
 
     // Currently running animation.
     boolean mAnimating;
@@ -138,19 +144,24 @@
     int mAttrFlags;
     int mAttrType;
 
-    public WindowStateAnimator(final WindowManagerService service, final WindowState win,
-                               final WindowState attachedWindow) {
+    public WindowStateAnimator(final WindowState win) {
+        final WindowManagerService service = win.mService;
+
         mService = service;
-        mWin = win;
-        mAttachedWindow = attachedWindow;
-        mAnimator = mService.mAnimator;
-        mSession = win.mSession;
-        mPolicy = mService.mPolicy;
-        mContext = mService.mContext;
-        mAttrFlags = win.mAttrs.flags;
-        mAttrType = win.mAttrs.type;
+        mAnimator = service.mAnimator;
+        mPolicy = service.mPolicy;
+        mContext = service.mContext;
         mAnimDw = service.mAppDisplayWidth;
         mAnimDh = service.mAppDisplayHeight;
+
+        mWin = win;
+        mAttachedWinAnimator = win.mAttachedWindow == null
+                ? null : win.mAttachedWindow.mWinAnimator;
+        mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
+        mSession = win.mSession;
+        mAttrFlags = win.mAttrs.flags;
+        mAttrType = win.mAttrs.type;
+        mIsWallpaper = win.mIsWallpaper;
     }
 
     public void setAnimation(Animation anim) {
@@ -177,20 +188,17 @@
 
     /** Is the window or its container currently animating? */
     boolean isAnimating() {
-        final WindowState attached = mAttachedWindow;
-        final AppWindowToken atoken = mWin.mAppToken;
         return mAnimation != null
-                || (attached != null && attached.mWinAnimator.mAnimation != null)
-                || (atoken != null &&
-                        (atoken.mAppAnimator.animation != null
-                                || atoken.inPendingTransaction));
+                || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
+                || (mAppAnimator != null &&
+                        (mAppAnimator.animation != null
+                                || mAppAnimator.mAppToken.inPendingTransaction));
     }
 
     /** Is the window animating the DummyAnimation? */
     boolean isDummyAnimation() {
-        final AppWindowToken atoken = mWin.mAppToken;
-        return atoken != null
-                && atoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
+        return mAppAnimator != null
+                && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
     }
 
     /** Is this window currently animating? */
@@ -213,7 +221,7 @@
         }
         mTransformation.clear();
         final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
-        if (DEBUG_ANIM) Slog.v(
+        if (false && DEBUG_ANIM) Slog.v(
             TAG, "Stepped animation in " + this +
             ": more=" + more + ", xform=" + mTransformation);
         return more;
@@ -257,8 +265,8 @@
                 //WindowManagerService.this.dump();
             }
             mHasLocalTransformation = false;
-            if ((!mLocalAnimating || mAnimationIsEntrance) && mWin.mAppToken != null
-                    && mWin.mAppToken.mAppAnimator.animation != null) {
+            if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null
+                    && mAppAnimator.animation != null) {
                 // When our app token is animating, we kind-of pretend like
                 // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
                 // part of this check means that we will only do this if
@@ -305,7 +313,7 @@
         mAnimLayer = mWin.mLayer;
         if (mWin.mIsImWindow) {
             mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
-        } else if (mWin.mIsWallpaper) {
+        } else if (mIsWallpaper) {
             mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
         }
         if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
@@ -689,10 +697,6 @@
                     mSurface.setAlpha(0);
                     mSurfaceShown = false;
                     mSurface.hide();
-                    if ((mWin.mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
-                        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "DITHER", null);
-                        mSurface.setFlags(Surface.SURFACE_DITHER, Surface.SURFACE_DITHER);
-                    }
                 } catch (RuntimeException e) {
                     Slog.w(TAG, "Error creating surface in " + w, e);
                     mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
@@ -799,31 +803,28 @@
     void computeShownFrameLocked() {
         final boolean selfTransformation = mHasLocalTransformation;
         Transformation attachedTransformation =
-                (mAttachedWindow != null && mAttachedWindow.mWinAnimator.mHasLocalTransformation)
-                ? mAttachedWindow.mWinAnimator.mTransformation : null;
-        final AppWindowAnimator appAnimator =
-                mWin.mAppToken == null ? null : mWin.mAppToken.mAppAnimator;
-        Transformation appTransformation = (appAnimator != null && appAnimator.hasTransformation)
-                ? appAnimator.transformation : null;
+                (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation)
+                ? mAttachedWinAnimator.mTransformation : null;
+        Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation)
+                ? mAppAnimator.transformation : null;
 
         // Wallpapers are animated based on the "real" window they
         // are currently targeting.
-        if (mWin.mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
-                && mService.mWallpaperTarget != null) {
-            if (mService.mWallpaperTarget.mWinAnimator.mHasLocalTransformation &&
-                    mService.mWallpaperTarget.mWinAnimator.mAnimation != null &&
-                    !mService.mWallpaperTarget.mWinAnimator.mAnimation.getDetachWallpaper()) {
-                attachedTransformation = mService.mWallpaperTarget.mWinAnimator.mTransformation;
+        if (mIsWallpaper && mAnimator.mLowerWallpaperTarget == null
+                && mAnimator.mWallpaperTarget != null) {
+            final WindowStateAnimator wallpaperAnimator = mAnimator.mWallpaperTarget.mWinAnimator;
+            if (wallpaperAnimator.mHasLocalTransformation &&
+                    wallpaperAnimator.mAnimation != null &&
+                    !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
+                attachedTransformation = wallpaperAnimator.mTransformation;
                 if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
                 }
             }
-            final AppWindowAnimator wpAppAnimator = mService.mWallpaperTarget.mAppToken == null
-                    ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
-            if (wpAppAnimator != null &&
-                    wpAppAnimator.hasTransformation &&
-                    wpAppAnimator.animation != null &&
-                    !wpAppAnimator.animation.getDetachWallpaper()) {
+            final AppWindowAnimator wpAppAnimator = mAnimator.mWpAppAnimator;
+            if (wpAppAnimator != null && wpAppAnimator.hasTransformation
+                    && wpAppAnimator.animation != null
+                    && !wpAppAnimator.animation.getDetachWallpaper()) {
                 appTransformation = wpAppAnimator.transformation;
                 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
                     Slog.v(TAG, "WP target app xform: " + appTransformation);
@@ -870,6 +871,9 @@
             if (appTransformation != null) {
                 tmpMatrix.postConcat(appTransformation.getMatrix());
             }
+            if (mAnimator.mUniverseBackground != null) {
+                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
+            }
             if (screenAnimation) {
                 tmpMatrix.postConcat(
                         mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix());
@@ -913,6 +917,9 @@
                 if (appTransformation != null) {
                     mShownAlpha *= appTransformation.getAlpha();
                 }
+                if (mAnimator.mUniverseBackground != null) {
+                    mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
+                }
                 if (screenAnimation) {
                     mShownAlpha *=
                         mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
@@ -921,7 +928,7 @@
                 //Slog.i(TAG, "Not applying alpha transform");
             }
 
-            if (WindowManagerService.localLOGV && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
+            if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV) && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
                 TAG, "computeShownFrameLocked: Animating " + this +
                 " mAlpha=" + mAlpha +
                 " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") +
@@ -930,7 +937,7 @@
                 " screen=" + (screenAnimation ? mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha()
                         : "null"));
             return;
-        } else if (mWin.mIsWallpaper &&
+        } else if (mIsWallpaper &&
                     (mAnimator.mPendingActions & WindowAnimator.WALLPAPER_ACTION_PENDING) != 0) {
             return;
         }
@@ -938,16 +945,64 @@
         if (WindowManagerService.localLOGV) Slog.v(
                 TAG, "computeShownFrameLocked: " + this +
                 " not attached, mAlpha=" + mAlpha);
-        mWin.mShownFrame.set(mWin.mFrame);
-        if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
-            mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+        if (mAnimator.mUniverseBackground != null &&
+                mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
+                && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer) {
+            final Rect frame = mWin.mFrame;
+            final float tmpFloats[] = mService.mTmpFloats;
+            final Matrix tmpMatrix = mWin.mTmpMatrix;
+            tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
+            tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
+            tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
+            tmpMatrix.getValues(tmpFloats);
+            mHaveMatrix = true;
+            mDsDx = tmpFloats[Matrix.MSCALE_X];
+            mDtDx = tmpFloats[Matrix.MSKEW_Y];
+            mDsDy = tmpFloats[Matrix.MSKEW_X];
+            mDtDy = tmpFloats[Matrix.MSCALE_Y];
+            float x = tmpFloats[Matrix.MTRANS_X];
+            float y = tmpFloats[Matrix.MTRANS_Y];
+            int w = frame.width();
+            int h = frame.height();
+            mWin.mShownFrame.set(x, y, x+w, y+h);
+            mShownAlpha = mAlpha * mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
+        } else {
+            mWin.mShownFrame.set(mWin.mFrame);
+            if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
+                mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+            }
+            mShownAlpha = mAlpha;
+            mHaveMatrix = false;
+            mDsDx = mWin.mGlobalScale;
+            mDtDx = 0;
+            mDsDy = 0;
+            mDtDy = mWin.mGlobalScale;
         }
-        mShownAlpha = mAlpha;
-        mHaveMatrix = false;
-        mDsDx = mWin.mGlobalScale;
-        mDtDx = 0;
-        mDsDy = 0;
-        mDtDy = mWin.mGlobalScale;
+    }
+
+    void applyDecorRect(final Rect decorRect) {
+        final WindowState w = mWin;
+        // Compute the offset of the window in relation to the decor rect.
+        final int offX = w.mXOffset + w.mFrame.left;
+        final int offY = w.mYOffset + w.mFrame.top;
+        // Initialize the decor rect to the entire frame.
+        w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
+        // Intersect with the decor rect, offsetted by window position.
+        w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
+                decorRect.right-offX, decorRect.bottom-offY);
+        // If size compatibility is being applied to the window, the
+        // surface is scaled relative to the screen.  Also apply this
+        // scaling to the crop rect.  We aren't using the standard rect
+        // scale function because we want to round things to make the crop
+        // always round to a larger rect to ensure we don't crop too
+        // much and hide part of the window that should be seen.
+        if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
+            final float scale = w.mInvGlobalScale;
+            w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
+            w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
+            w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
+            w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
+        }
     }
 
     void updateSurfaceWindowCrop(final boolean recoveringMemory) {
@@ -960,31 +1015,21 @@
             w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
         } else if (w.mLayer >= mService.mSystemDecorLayer) {
             // Above the decor layer is easy, just use the entire window.
+            // Unless we have a universe background...  in which case all the
+            // windows need to be cropped by the screen, so they don't cover
+            // the universe background.
+            if (mAnimator.mUniverseBackground == null) {
+                w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
+                        w.mCompatFrame.height());
+            } else {
+                applyDecorRect(mService.mScreenRect);
+            }
+        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
+            // The universe background isn't cropped.
             w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
                     w.mCompatFrame.height());
         } else {
-            final Rect decorRect = mService.mSystemDecorRect;
-            // Compute the offset of the window in relation to the decor rect.
-            final int offX = w.mXOffset + w.mFrame.left;
-            final int offY = w.mYOffset + w.mFrame.top;
-            // Initialize the decor rect to the entire frame.
-            w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
-            // Intersect with the decor rect, offsetted by window position.
-            w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
-                    decorRect.right-offX, decorRect.bottom-offY);
-            // If size compatibility is being applied to the window, the
-            // surface is scaled relative to the screen.  Also apply this
-            // scaling to the crop rect.  We aren't using the standard rect
-            // scale function because we want to round things to make the crop
-            // always round to a larger rect to ensure we don't crop too
-            // much and hide part of the window that should be seen.
-            if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
-                final float scale = w.mInvGlobalScale;
-                w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
-                w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
-                w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
-                w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
-            }
+            applyDecorRect(mService.mSystemDecorRect);
         }
 
         if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
@@ -1056,7 +1101,7 @@
                 mAnimator.mPendingLayoutChanges |=
                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
-                    mAnimator.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
+                    mService.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
                             mService.mAppDisplayWidth, mService.mAppDisplayHeight);
                 }
             } catch (RuntimeException e) {
@@ -1092,7 +1137,7 @@
 
         setSurfaceBoundaries(recoveringMemory);
 
-        if (mWin.mIsWallpaper && !mWin.mWallpaperVisible) {
+        if (mIsWallpaper && !mWin.mWallpaperVisible) {
             // Wallpaper is no longer visible and there is no wp target => hide it.
             hide();
         } else if (w.mAttachedHidden || !w.isReadyForDisplay()) {
@@ -1151,7 +1196,7 @@
                                 + " during relayout");
                         if (showSurfaceRobustlyLocked()) {
                             mLastHidden = false;
-                            if (w.mIsWallpaper) {
+                            if (mIsWallpaper) {
                                 mService.dispatchWallpaperVisibility(w, true);
                             }
                         } else {
@@ -1169,8 +1214,8 @@
                 }
             }
         } else {
-            if (DEBUG_ANIM) {
-                // Slog.v(TAG, "prepareSurface: No changes in animation for " + mWin);
+            if (DEBUG_ANIM && isAnimating()) {
+                Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
             }
             displayed = true;
         }
@@ -1178,7 +1223,7 @@
         if (displayed) {
             if (w.mOrientationChanging) {
                 if (!w.isDrawnLw()) {
-                    mAnimator.mBulkUpdateParams |= CLEAR_ORIENTATION_CHANGE_COMPLETE;
+                    mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
                     if (DEBUG_ORIENTATION) Slog.v(TAG,
                             "Orientation continue waiting for draw in " + w);
                 } else {
@@ -1258,7 +1303,7 @@
                     + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
                     + " animating=" + mAnimating
                     + " tok animating="
-                    + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false), e);
+                    + (mAppAnimator != null ? mAppAnimator.animating : false), e);
         }
         if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) {
             if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
@@ -1274,7 +1319,7 @@
                         + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
                         + " animating=" + mAnimating
                         + " tok animating="
-                        + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false));
+                        + (mAppAnimator != null ? mAppAnimator.animating : false));
             }
 
             mService.enableScreenIfNeededLocked();
@@ -1286,7 +1331,7 @@
             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM)
                 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this);
             mDrawState = HAS_DRAWN;
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
 
             int i = mWin.mChildWindows.size();
             while (i > 0) {
@@ -1483,6 +1528,11 @@
             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
         }
+        if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
+            pw.print(prefix); pw.print("mUniverseTransform=");
+                    mUniverseTransform.printShortString(pw);
+                    pw.println();
+        }
         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
                     pw.print(" mAlpha="); pw.print(mAlpha);
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index e0a14af..d097a93 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -8,7 +8,7 @@
     com_android_server_input_InputManagerService.cpp \
     com_android_server_input_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
-    com_android_server_PowerManagerService.cpp \
+    com_android_server_power_PowerManagerService.cpp \
     com_android_server_SerialService.cpp \
     com_android_server_SystemServer.cpp \
     com_android_server_UsbDeviceManager.cpp \
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 0e1ce51..57e1c28 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -49,7 +49,7 @@
 #include <ScopedLocalRef.h>
 #include <ScopedUtfChars.h>
 
-#include "com_android_server_PowerManagerService.h"
+#include "com_android_server_power_PowerManagerService.h"
 #include "com_android_server_input_InputApplicationHandle.h"
 #include "com_android_server_input_InputWindowHandle.h"
 
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_power_PowerManagerService.cpp
similarity index 96%
rename from services/jni/com_android_server_PowerManagerService.cpp
rename to services/jni/com_android_server_power_PowerManagerService.cpp
index 0904bdd..2690b68 100644
--- a/services/jni/com_android_server_PowerManagerService.cpp
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -35,7 +35,7 @@
 
 #include <private/gui/ComposerService.h>
 
-#include "com_android_server_PowerManagerService.h"
+#include "com_android_server_power_PowerManagerService.h"
 
 namespace android {
 
@@ -177,12 +177,15 @@
 }
 
 static int nativeSetScreenState(JNIEnv *env, jobject clazz, jboolean on) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (on) {
         autosuspend_disable();
         if (gPowerModule) {
             gPowerModule->setInteractive(gPowerModule, true);
         }
+        s->unblank();
     } else {
+        s->blank();
         if (gPowerModule) {
             gPowerModule->setInteractive(gPowerModule, false);
         }
@@ -243,14 +246,14 @@
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_PowerManagerService(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/PowerManagerService",
+    int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
             gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     // Callbacks
 
     jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/PowerManagerService");
+    FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
 
     GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, clazz,
             "goToSleep", "(J)V");
diff --git a/services/jni/com_android_server_PowerManagerService.h b/services/jni/com_android_server_power_PowerManagerService.h
similarity index 100%
rename from services/jni/com_android_server_PowerManagerService.h
rename to services/jni/com_android_server_power_PowerManagerService.h
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
deleted file mode 100644
index 6a302c0..0000000
--- a/services/sensorservice/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	CorrectedGyroSensor.cpp \
-    Fusion.cpp \
-    GravitySensor.cpp \
-    LinearAccelerationSensor.cpp \
-    OrientationSensor.cpp \
-    RotationVectorSensor.cpp \
-    SensorDevice.cpp \
-    SensorFusion.cpp \
-    SensorInterface.cpp \
-    SensorService.cpp \
-
-
-LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libhardware \
-	libutils \
-	libbinder \
-	libui \
-	libgui
-
-
-
-LOCAL_MODULE:= libsensorservice
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
deleted file mode 100644
index 1857443..0000000
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "CorrectedGyroSensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-CorrectedGyroSensor::CorrectedGyroSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    for (size_t i=0 ; i<count ; i++) {
-        if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
-            mGyro = Sensor(list + i);
-            break;
-        }
-    }
-}
-
-bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_GYROSCOPE) {
-        const vec3_t bias(mSensorFusion.getGyroBias());
-        *outEvent = event;
-        outEvent->data[0] -= bias.x;
-        outEvent->data[1] -= bias.y;
-        outEvent->data[2] -= bias.z;
-        outEvent->sensor = '_cgy';
-        return true;
-    }
-    return false;
-}
-
-status_t CorrectedGyroSensor::activate(void* ident, bool enabled) {
-    mSensorDevice.activate(this, mGyro.getHandle(), enabled);
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t CorrectedGyroSensor::setDelay(void* ident, int handle, int64_t ns) {
-    mSensorDevice.setDelay(this, mGyro.getHandle(), ns);
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor CorrectedGyroSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Corrected Gyroscope Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_cgy';
-    hwSensor.type       = SENSOR_TYPE_GYROSCOPE;
-    hwSensor.maxRange   = mGyro.getMaxValue();
-    hwSensor.resolution = mGyro.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mGyro.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
deleted file mode 100644
index 3c49c08..0000000
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_CORRECTED_GYRO_SENSOR_H
-#define ANDROID_CORRECTED_GYRO_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class CorrectedGyroSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    Sensor mGyro;
-
-public:
-    CorrectedGyroSensor(sensor_t const* list, size_t count);
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_CORRECTED_GYRO_SENSOR_H
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
deleted file mode 100644
index b724ce2..0000000
--- a/services/sensorservice/Fusion.cpp
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-
-#include <utils/Log.h>
-
-#include "Fusion.h"
-
-namespace android {
-
-// -----------------------------------------------------------------------
-
-/*
- * gyroVAR gives the measured variance of the gyro's output per
- * Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
- * which is independent of the sampling frequency.
- *
- * The variance of gyro's output at a given sampling period can be
- * calculated as:
- *      variance(T) = gyroVAR / T
- *
- * The variance of the INTEGRATED OUTPUT at a given sampling period can be
- * calculated as:
- *       variance_integrate_output(T) = gyroVAR * T
- *
- */
-static const float gyroVAR = 1e-7;      // (rad/s)^2 / Hz
-static const float biasVAR = 1e-8;      // (rad/s)^2 / s (guessed)
-
-/*
- * Standard deviations of accelerometer and magnetometer
- */
-static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
-static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
-
-static const float SYMMETRY_TOLERANCE = 1e-10f;
-
-/*
- * Accelerometer updates will not be performed near free fall to avoid
- * ill-conditioning and div by zeros.
- * Threshhold: 10% of g, in m/s^2
- */
-static const float FREE_FALL_THRESHOLD = 0.981f;
-static const float FREE_FALL_THRESHOLD_SQ =
-        FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD;
-
-/*
- * The geomagnetic-field should be between 30uT and 60uT.
- * Fields strengths greater than this likely indicate a local magnetic
- * disturbance which we do not want to update into the fused frame.
- */
-static const float MAX_VALID_MAGNETIC_FIELD = 100; // uT
-static const float MAX_VALID_MAGNETIC_FIELD_SQ =
-        MAX_VALID_MAGNETIC_FIELD*MAX_VALID_MAGNETIC_FIELD;
-
-/*
- * Values of the field smaller than this should be ignored in fusion to avoid
- * ill-conditioning. This state can happen with anomalous local magnetic
- * disturbances canceling the Earth field.
- */
-static const float MIN_VALID_MAGNETIC_FIELD = 10; // uT
-static const float MIN_VALID_MAGNETIC_FIELD_SQ =
-        MIN_VALID_MAGNETIC_FIELD*MIN_VALID_MAGNETIC_FIELD;
-
-/*
- * If the cross product of two vectors has magnitude squared less than this,
- * we reject it as invalid due to alignment of the vectors.
- * This threshold is used to check for the case where the magnetic field sample
- * is parallel to the gravity field, which can happen in certain places due
- * to magnetic field disturbances.
- */
-static const float MIN_VALID_CROSS_PRODUCT_MAG = 1.0e-3;
-static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ =
-    MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG;
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t C, size_t R>
-static mat<TYPE, R, R> scaleCovariance(
-        const mat<TYPE, C, R>& A,
-        const mat<TYPE, C, C>& P) {
-    // A*P*transpose(A);
-    mat<TYPE, R, R> APAt;
-    for (size_t r=0 ; r<R ; r++) {
-        for (size_t j=r ; j<R ; j++) {
-            double apat(0);
-            for (size_t c=0 ; c<C ; c++) {
-                double v(A[c][r]*P[c][c]*0.5);
-                for (size_t k=c+1 ; k<C ; k++)
-                    v += A[k][r] * P[c][k];
-                apat += 2 * v * A[c][j];
-            }
-            APAt[j][r] = apat;
-            APAt[r][j] = apat;
-        }
-    }
-    return APAt;
-}
-
-template <typename TYPE, typename OTHER_TYPE>
-static mat<TYPE, 3, 3> crossMatrix(const vec<TYPE, 3>& p, OTHER_TYPE diag) {
-    mat<TYPE, 3, 3> r;
-    r[0][0] = diag;
-    r[1][1] = diag;
-    r[2][2] = diag;
-    r[0][1] = p.z;
-    r[1][0] =-p.z;
-    r[0][2] =-p.y;
-    r[2][0] = p.y;
-    r[1][2] = p.x;
-    r[2][1] =-p.x;
-    return r;
-}
-
-
-template<typename TYPE, size_t SIZE>
-class Covariance {
-    mat<TYPE, SIZE, SIZE> mSumXX;
-    vec<TYPE, SIZE> mSumX;
-    size_t mN;
-public:
-    Covariance() : mSumXX(0.0f), mSumX(0.0f), mN(0) { }
-    void update(const vec<TYPE, SIZE>& x) {
-        mSumXX += x*transpose(x);
-        mSumX  += x;
-        mN++;
-    }
-    mat<TYPE, SIZE, SIZE> operator()() const {
-        const float N = 1.0f / mN;
-        return mSumXX*N - (mSumX*transpose(mSumX))*(N*N);
-    }
-    void reset() {
-        mN = 0;
-        mSumXX = 0;
-        mSumX = 0;
-    }
-    size_t getCount() const {
-        return mN;
-    }
-};
-
-// -----------------------------------------------------------------------
-
-Fusion::Fusion() {
-    Phi[0][1] = 0;
-    Phi[1][1] = 1;
-
-    Ba.x = 0;
-    Ba.y = 0;
-    Ba.z = 1;
-
-    Bm.x = 0;
-    Bm.y = 1;
-    Bm.z = 0;
-
-    x0 = 0;
-    x1 = 0;
-
-    init();
-}
-
-void Fusion::init() {
-    mInitState = 0;
-
-    mGyroRate = 0;
-
-    mCount[0] = 0;
-    mCount[1] = 0;
-    mCount[2] = 0;
-
-    mData = 0;
-}
-
-void Fusion::initFusion(const vec4_t& q, float dT)
-{
-    // initial estimate: E{ x(t0) }
-    x0 = q;
-    x1 = 0;
-
-    // process noise covariance matrix: G.Q.Gt, with
-    //
-    //  G = | -1 0 |        Q = | q00 q10 |
-    //      |  0 1 |            | q01 q11 |
-    //
-    // q00 = sv^2.dt + 1/3.su^2.dt^3
-    // q10 = q01 = 1/2.su^2.dt^2
-    // q11 = su^2.dt
-    //
-
-    // variance of integrated output at 1/dT Hz
-    // (random drift)
-    const float q00 = gyroVAR * dT;
-
-    // variance of drift rate ramp
-    const float q11 = biasVAR * dT;
-
-    const float u   = q11 / dT;
-    const float q10 = 0.5f*u*dT*dT;
-    const float q01 = q10;
-
-    GQGt[0][0] =  q00;      // rad^2
-    GQGt[1][0] = -q10;
-    GQGt[0][1] = -q01;
-    GQGt[1][1] =  q11;      // (rad/s)^2
-
-    // initial covariance: Var{ x(t0) }
-    // TODO: initialize P correctly
-    P = 0;
-}
-
-bool Fusion::hasEstimate() const {
-    return (mInitState == (MAG|ACC|GYRO));
-}
-
-bool Fusion::checkInitComplete(int what, const vec3_t& d, float dT) {
-    if (hasEstimate())
-        return true;
-
-    if (what == ACC) {
-        mData[0] += d * (1/length(d));
-        mCount[0]++;
-        mInitState |= ACC;
-    } else if (what == MAG) {
-        mData[1] += d * (1/length(d));
-        mCount[1]++;
-        mInitState |= MAG;
-    } else if (what == GYRO) {
-        mGyroRate = dT;
-        mData[2] += d*dT;
-        mCount[2]++;
-        if (mCount[2] == 64) {
-            // 64 samples is good enough to estimate the gyro drift and
-            // doesn't take too much time.
-            mInitState |= GYRO;
-        }
-    }
-
-    if (mInitState == (MAG|ACC|GYRO)) {
-        // Average all the values we collected so far
-        mData[0] *= 1.0f/mCount[0];
-        mData[1] *= 1.0f/mCount[1];
-        mData[2] *= 1.0f/mCount[2];
-
-        // calculate the MRPs from the data collection, this gives us
-        // a rough estimate of our initial state
-        mat33_t R;
-        vec3_t up(mData[0]);
-        vec3_t east(cross_product(mData[1], up));
-        east *= 1/length(east);
-        vec3_t north(cross_product(up, east));
-        R << east << north << up;
-        const vec4_t q = matrixToQuat(R);
-
-        initFusion(q, mGyroRate);
-    }
-
-    return false;
-}
-
-void Fusion::handleGyro(const vec3_t& w, float dT) {
-    if (!checkInitComplete(GYRO, w, dT))
-        return;
-
-    predict(w, dT);
-}
-
-status_t Fusion::handleAcc(const vec3_t& a) {
-    // ignore acceleration data if we're close to free-fall
-    if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) {
-        return BAD_VALUE;
-    }
-
-    if (!checkInitComplete(ACC, a))
-        return BAD_VALUE;
-
-    const float l = 1/length(a);
-    update(a*l, Ba, accSTDEV*l);
-    return NO_ERROR;
-}
-
-status_t Fusion::handleMag(const vec3_t& m) {
-    // the geomagnetic-field should be between 30uT and 60uT
-    // reject if too large to avoid spurious magnetic sources
-    const float magFieldSq = length_squared(m);
-    if (magFieldSq > MAX_VALID_MAGNETIC_FIELD_SQ) {
-        return BAD_VALUE;
-    } else if (magFieldSq < MIN_VALID_MAGNETIC_FIELD_SQ) {
-        // Also reject if too small since we will get ill-defined (zero mag)
-        // cross-products below
-        return BAD_VALUE;
-    }
-
-    if (!checkInitComplete(MAG, m))
-        return BAD_VALUE;
-
-    // Orthogonalize the magnetic field to the gravity field, mapping it into
-    // tangent to Earth.
-    const vec3_t up( getRotationMatrix() * Ba );
-    const vec3_t east( cross_product(m, up) );
-
-    // If the m and up vectors align, the cross product magnitude will
-    // approach 0.
-    // Reject this case as well to avoid div by zero problems and
-    // ill-conditioning below.
-    if (length_squared(east) < MIN_VALID_CROSS_PRODUCT_MAG_SQ) {
-        return BAD_VALUE;
-    }
-
-    // If we have created an orthogonal magnetic field successfully,
-    // then pass it in as the update.
-    vec3_t north( cross_product(up, east) );
-
-    const float l = 1 / length(north);
-    north *= l;
-
-    update(north, Bm, magSTDEV*l);
-    return NO_ERROR;
-}
-
-void Fusion::checkState() {
-    // P needs to stay positive semidefinite or the fusion diverges. When we
-    // detect divergence, we reset the fusion.
-    // TODO(braun): Instead, find the reason for the divergence and fix it.
-
-    if (!isPositiveSemidefinite(P[0][0], SYMMETRY_TOLERANCE) ||
-        !isPositiveSemidefinite(P[1][1], SYMMETRY_TOLERANCE)) {
-        ALOGW("Sensor fusion diverged; resetting state.");
-        P = 0;
-    }
-}
-
-vec4_t Fusion::getAttitude() const {
-    return x0;
-}
-
-vec3_t Fusion::getBias() const {
-    return x1;
-}
-
-mat33_t Fusion::getRotationMatrix() const {
-    return quatToMatrix(x0);
-}
-
-mat34_t Fusion::getF(const vec4_t& q) {
-    mat34_t F;
-    F[0].x = q.w;   F[1].x =-q.z;   F[2].x = q.y;
-    F[0].y = q.z;   F[1].y = q.w;   F[2].y =-q.x;
-    F[0].z =-q.y;   F[1].z = q.x;   F[2].z = q.w;
-    F[0].w =-q.x;   F[1].w =-q.y;   F[2].w =-q.z;
-    return F;
-}
-
-void Fusion::predict(const vec3_t& w, float dT) {
-    const vec4_t q  = x0;
-    const vec3_t b  = x1;
-    const vec3_t we = w - b;
-    const vec4_t dq = getF(q)*((0.5f*dT)*we);
-    x0 = normalize_quat(q + dq);
-
-    // P(k+1) = F*P(k)*Ft + G*Q*Gt
-
-    //  Phi = | Phi00 Phi10 |
-    //        |   0     1   |
-    const mat33_t I33(1);
-    const mat33_t I33dT(dT);
-    const mat33_t wx(crossMatrix(we, 0));
-    const mat33_t wx2(wx*wx);
-    const float lwedT = length(we)*dT;
-    const float ilwe = 1/length(we);
-    const float k0 = (1-cosf(lwedT))*(ilwe*ilwe);
-    const float k1 = sinf(lwedT);
-
-    Phi[0][0] = I33 - wx*(k1*ilwe) + wx2*k0;
-    Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1);
-
-    P = Phi*P*transpose(Phi) + GQGt;
-
-    checkState();
-}
-
-void Fusion::update(const vec3_t& z, const vec3_t& Bi, float sigma) {
-    vec4_t q(x0);
-    // measured vector in body space: h(p) = A(p)*Bi
-    const mat33_t A(quatToMatrix(q));
-    const vec3_t Bb(A*Bi);
-
-    // Sensitivity matrix H = dh(p)/dp
-    // H = [ L 0 ]
-    const mat33_t L(crossMatrix(Bb, 0));
-
-    // gain...
-    // K = P*Ht / [H*P*Ht + R]
-    vec<mat33_t, 2> K;
-    const mat33_t R(sigma*sigma);
-    const mat33_t S(scaleCovariance(L, P[0][0]) + R);
-    const mat33_t Si(invert(S));
-    const mat33_t LtSi(transpose(L)*Si);
-    K[0] = P[0][0] * LtSi;
-    K[1] = transpose(P[1][0])*LtSi;
-
-    // update...
-    // P -= K*H*P;
-    const mat33_t K0L(K[0] * L);
-    const mat33_t K1L(K[1] * L);
-    P[0][0] -= K0L*P[0][0];
-    P[1][1] -= K1L*P[1][0];
-    P[1][0] -= K0L*P[1][0];
-    P[0][1] = transpose(P[1][0]);
-
-    const vec3_t e(z - Bb);
-    const vec3_t dq(K[0]*e);
-    const vec3_t db(K[1]*e);
-
-    q += getF(q)*(0.5f*dq);
-    x0 = normalize_quat(q);
-    x1 += db;
-
-    checkState();
-}
-
-// -----------------------------------------------------------------------
-
-}; // namespace android
-
diff --git a/services/sensorservice/Fusion.h b/services/sensorservice/Fusion.h
deleted file mode 100644
index 7062999..0000000
--- a/services/sensorservice/Fusion.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_FUSION_H
-#define ANDROID_FUSION_H
-
-#include <utils/Errors.h>
-
-#include "quat.h"
-#include "mat.h"
-#include "vec.h"
-
-namespace android {
-
-typedef mat<float, 3, 4> mat34_t;
-
-class Fusion {
-    /*
-     * the state vector is made of two sub-vector containing respectively:
-     * - modified Rodrigues parameters
-     * - the estimated gyro bias
-     */
-    quat_t  x0;
-    vec3_t  x1;
-
-    /*
-     * the predicated covariance matrix is made of 4 3x3 sub-matrices and it is
-     * semi-definite positive.
-     *
-     * P = | P00  P10 | = | P00  P10 |
-     *     | P01  P11 |   | P10t P11 |
-     *
-     * Since P01 = transpose(P10), the code below never calculates or
-     * stores P01.
-     */
-    mat<mat33_t, 2, 2> P;
-
-    /*
-     * the process noise covariance matrix
-     */
-    mat<mat33_t, 2, 2> GQGt;
-
-public:
-    Fusion();
-    void init();
-    void handleGyro(const vec3_t& w, float dT);
-    status_t handleAcc(const vec3_t& a);
-    status_t handleMag(const vec3_t& m);
-    vec4_t getAttitude() const;
-    vec3_t getBias() const;
-    mat33_t getRotationMatrix() const;
-    bool hasEstimate() const;
-
-private:
-    mat<mat33_t, 2, 2> Phi;
-    vec3_t Ba, Bm;
-    uint32_t mInitState;
-    float mGyroRate;
-    vec<vec3_t, 3> mData;
-    size_t mCount[3];
-    enum { ACC=0x1, MAG=0x2, GYRO=0x4 };
-    bool checkInitComplete(int, const vec3_t& w, float d = 0);
-    void initFusion(const vec4_t& q0, float dT);
-    void checkState();
-    void predict(const vec3_t& w, float dT);
-    void update(const vec3_t& z, const vec3_t& Bi, float sigma);
-    static mat34_t getF(const vec4_t& p);
-};
-
-}; // namespace android
-
-#endif // ANDROID_FUSION_H
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
deleted file mode 100644
index c57715f..0000000
--- a/services/sensorservice/GravitySensor.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "GravitySensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-GravitySensor::GravitySensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    for (size_t i=0 ; i<count ; i++) {
-        if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
-            mAccelerometer = Sensor(list + i);
-            break;
-        }
-    }
-}
-
-bool GravitySensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    const static double NS2S = 1.0 / 1000000000.0;
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        vec3_t g;
-        if (!mSensorFusion.hasEstimate())
-            return false;
-        const mat33_t R(mSensorFusion.getRotationMatrix());
-        // FIXME: we need to estimate the length of gravity because
-        // the accelerometer may have a small scaling error. This
-        // translates to an offset in the linear-acceleration sensor.
-        g = R[2] * GRAVITY_EARTH;
-
-        *outEvent = event;
-        outEvent->data[0] = g.x;
-        outEvent->data[1] = g.y;
-        outEvent->data[2] = g.z;
-        outEvent->sensor = '_grv';
-        outEvent->type = SENSOR_TYPE_GRAVITY;
-        return true;
-    }
-    return false;
-}
-
-status_t GravitySensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor GravitySensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Gravity Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_grv';
-    hwSensor.type       = SENSOR_TYPE_GRAVITY;
-    hwSensor.maxRange   = GRAVITY_EARTH * 2;
-    hwSensor.resolution = mAccelerometer.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
deleted file mode 100644
index ac177c4..0000000
--- a/services/sensorservice/GravitySensor.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GRAVITY_SENSOR_H
-#define ANDROID_GRAVITY_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class GravitySensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    Sensor mAccelerometer;
-
-public:
-    GravitySensor(sensor_t const* list, size_t count);
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GRAVITY_SENSOR_H
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
deleted file mode 100644
index f0054f2..0000000
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "LinearAccelerationSensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mGravitySensor(list, count)
-{
-}
-
-bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    bool result = mGravitySensor.process(outEvent, event);
-    if (result && event.type == SENSOR_TYPE_ACCELEROMETER) {
-        outEvent->data[0] = event.acceleration.x - outEvent->data[0];
-        outEvent->data[1] = event.acceleration.y - outEvent->data[1];
-        outEvent->data[2] = event.acceleration.z - outEvent->data[2];
-        outEvent->sensor = '_lin';
-        outEvent->type = SENSOR_TYPE_LINEAR_ACCELERATION;
-        return true;
-    }
-    return false;
-}
-
-status_t LinearAccelerationSensor::activate(void* ident, bool enabled) {
-    return mGravitySensor.activate(this, enabled);
-}
-
-status_t LinearAccelerationSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mGravitySensor.setDelay(this, handle, ns);
-}
-
-Sensor LinearAccelerationSensor::getSensor() const {
-    Sensor gsensor(mGravitySensor.getSensor());
-    sensor_t hwSensor;
-    hwSensor.name       = "Linear Acceleration Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = gsensor.getVersion();
-    hwSensor.handle     = '_lin';
-    hwSensor.type       = SENSOR_TYPE_LINEAR_ACCELERATION;
-    hwSensor.maxRange   = gsensor.getMaxValue();
-    hwSensor.resolution = gsensor.getResolution();
-    hwSensor.power      = gsensor.getPowerUsage();
-    hwSensor.minDelay   = gsensor.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
deleted file mode 100644
index 5deb24f..0000000
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LINEAR_ACCELERATION_SENSOR_H
-#define ANDROID_LINEAR_ACCELERATION_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-#include "GravitySensor.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class LinearAccelerationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    GravitySensor mGravitySensor;
-
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-public:
-    LinearAccelerationSensor(sensor_t const* list, size_t count);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_LINEAR_ACCELERATION_SENSOR_H
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
deleted file mode 100644
index 037adaa..0000000
--- a/services/sensorservice/OrientationSensor.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "OrientationSensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-OrientationSensor::OrientationSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-}
-
-bool OrientationSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            vec3_t g;
-            const float rad2deg = 180 / M_PI;
-            const mat33_t R(mSensorFusion.getRotationMatrix());
-            g[0] = atan2f(-R[1][0], R[0][0])    * rad2deg;
-            g[1] = atan2f(-R[2][1], R[2][2])    * rad2deg;
-            g[2] = asinf ( R[2][0])             * rad2deg;
-            if (g[0] < 0)
-                g[0] += 360;
-
-            *outEvent = event;
-            outEvent->orientation.azimuth = g.x;
-            outEvent->orientation.pitch   = g.y;
-            outEvent->orientation.roll    = g.z;
-            outEvent->orientation.status  = SENSOR_STATUS_ACCURACY_HIGH;
-            outEvent->sensor = '_ypr';
-            outEvent->type = SENSOR_TYPE_ORIENTATION;
-            return true;
-        }
-    }
-    return false;
-}
-
-status_t OrientationSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t OrientationSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor OrientationSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Orientation Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_ypr';
-    hwSensor.type       = SENSOR_TYPE_ORIENTATION;
-    hwSensor.maxRange   = 360.0f;
-    hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
deleted file mode 100644
index 855949d..0000000
--- a/services/sensorservice/OrientationSensor.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_ORIENTATION_SENSOR_H
-#define ANDROID_ORIENTATION_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class OrientationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
-public:
-    OrientationSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_ORIENTATION_SENSOR_H
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
deleted file mode 100644
index 5ea9568..0000000
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "RotationVectorSensor.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-RotationVectorSensor::RotationVectorSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-}
-
-bool RotationVectorSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            const vec4_t q(mSensorFusion.getAttitude());
-            *outEvent = event;
-            outEvent->data[0] = q.x;
-            outEvent->data[1] = q.y;
-            outEvent->data[2] = q.z;
-            outEvent->data[3] = q.w;
-            outEvent->sensor = '_rov';
-            outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
-            return true;
-        }
-    }
-    return false;
-}
-
-status_t RotationVectorSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t RotationVectorSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor RotationVectorSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Rotation Vector Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_rov';
-    hwSensor.type       = SENSOR_TYPE_ROTATION_VECTOR;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-
-GyroDriftSensor::GyroDriftSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-}
-
-bool GyroDriftSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            const vec3_t b(mSensorFusion.getGyroBias());
-            *outEvent = event;
-            outEvent->data[0] = b.x;
-            outEvent->data[1] = b.y;
-            outEvent->data[2] = b.z;
-            outEvent->sensor = '_gbs';
-            outEvent->type = SENSOR_TYPE_ACCELEROMETER;
-            return true;
-        }
-    }
-    return false;
-}
-
-status_t GyroDriftSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t GyroDriftSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor GyroDriftSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Gyroscope Bias (debug)";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_gbs';
-    hwSensor.type       = SENSOR_TYPE_ACCELEROMETER;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
deleted file mode 100644
index bb97fe1..0000000
--- a/services/sensorservice/RotationVectorSensor.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_ROTATION_VECTOR_SENSOR_H
-#define ANDROID_ROTATION_VECTOR_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorDevice.h"
-#include "SensorInterface.h"
-
-#include "Fusion.h"
-#include "SensorFusion.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class RotationVectorSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
-public:
-    RotationVectorSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-class GyroDriftSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
-public:
-    GyroDriftSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_ROTATION_VECTOR_SENSOR_H
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
deleted file mode 100644
index 2244a86..0000000
--- a/services/sensorservice/SensorDevice.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
-#include <binder/BinderService.h>
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-
-#include <hardware/sensors.h>
-
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-class BatteryService : public Singleton<BatteryService> {
-    static const int TRANSACTION_noteStartSensor = IBinder::FIRST_CALL_TRANSACTION + 3;
-    static const int TRANSACTION_noteStopSensor = IBinder::FIRST_CALL_TRANSACTION + 4;
-    static const String16 DESCRIPTOR;
-
-    friend class Singleton<BatteryService>;
-    sp<IBinder> mBatteryStatService;
-
-    BatteryService() {
-        const sp<IServiceManager> sm(defaultServiceManager());
-        if (sm != NULL) {
-            const String16 name("batteryinfo");
-            mBatteryStatService = sm->getService(name);
-        }
-    }
-
-    status_t noteStartSensor(int uid, int handle) {
-        Parcel data, reply;
-        data.writeInterfaceToken(DESCRIPTOR);
-        data.writeInt32(uid);
-        data.writeInt32(handle);
-        status_t err = mBatteryStatService->transact(
-                TRANSACTION_noteStartSensor, data, &reply, 0);
-        err = reply.readExceptionCode();
-        return err;
-    }
-
-    status_t noteStopSensor(int uid, int handle) {
-        Parcel data, reply;
-        data.writeInterfaceToken(DESCRIPTOR);
-        data.writeInt32(uid);
-        data.writeInt32(handle);
-        status_t err = mBatteryStatService->transact(
-                TRANSACTION_noteStopSensor, data, &reply, 0);
-        err = reply.readExceptionCode();
-        return err;
-    }
-
-public:
-    void enableSensor(int handle) {
-        if (mBatteryStatService != 0) {
-            int uid = IPCThreadState::self()->getCallingUid();
-            int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-            noteStartSensor(uid, handle);
-            IPCThreadState::self()->restoreCallingIdentity(identity);
-        }
-    }
-    void disableSensor(int handle) {
-        if (mBatteryStatService != 0) {
-            int uid = IPCThreadState::self()->getCallingUid();
-            int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-            noteStopSensor(uid, handle);
-            IPCThreadState::self()->restoreCallingIdentity(identity);
-        }
-    }
-};
-
-const String16 BatteryService::DESCRIPTOR("com.android.internal.app.IBatteryStats");
-
-ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
-
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
-
-SensorDevice::SensorDevice()
-    :  mSensorDevice(0),
-       mSensorModule(0)
-{
-    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
-            (hw_module_t const**)&mSensorModule);
-
-    ALOGE_IF(err, "couldn't load %s module (%s)",
-            SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
-    if (mSensorModule) {
-        err = sensors_open(&mSensorModule->common, &mSensorDevice);
-
-        ALOGE_IF(err, "couldn't open device for module %s (%s)",
-                SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
-        if (mSensorDevice) {
-            sensor_t const* list;
-            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
-            mActivationCount.setCapacity(count);
-            Info model;
-            for (size_t i=0 ; i<size_t(count) ; i++) {
-                mActivationCount.add(list[i].handle, model);
-                mSensorDevice->activate(mSensorDevice, list[i].handle, 0);
-            }
-        }
-    }
-}
-
-void SensorDevice::dump(String8& result, char* buffer, size_t SIZE)
-{
-    if (!mSensorModule) return;
-    sensor_t const* list;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
-
-    snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count));
-    result.append(buffer);
-
-    Mutex::Autolock _l(mLock);
-    for (size_t i=0 ; i<size_t(count) ; i++) {
-        const Info& info = mActivationCount.valueFor(list[i].handle);
-        snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ",
-                list[i].handle,
-                info.rates.size());
-        result.append(buffer);
-        for (size_t j=0 ; j<info.rates.size() ; j++) {
-            snprintf(buffer, SIZE, "%4.1f%s",
-                    info.rates.valueAt(j) / 1e6f,
-                    j<info.rates.size()-1 ? ", " : "");
-            result.append(buffer);
-        }
-        snprintf(buffer, SIZE, " }, selected=%4.1f ms\n",  info.delay / 1e6f);
-        result.append(buffer);
-    }
-}
-
-ssize_t SensorDevice::getSensorList(sensor_t const** list) {
-    if (!mSensorModule) return NO_INIT;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
-    return count;
-}
-
-status_t SensorDevice::initCheck() const {
-    return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
-}
-
-ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
-    if (!mSensorDevice) return NO_INIT;
-    ssize_t c;
-    do {
-        c = mSensorDevice->poll(mSensorDevice, buffer, count);
-    } while (c == -EINTR);
-    return c;
-}
-
-status_t SensorDevice::activate(void* ident, int handle, int enabled)
-{
-    if (!mSensorDevice) return NO_INIT;
-    status_t err(NO_ERROR);
-    bool actuateHardware = false;
-
-    Info& info( mActivationCount.editValueFor(handle) );
-
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-            "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
-            ident, handle, enabled, info.rates.size());
-
-    if (enabled) {
-        Mutex::Autolock _l(mLock);
-        ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
-                info.rates.indexOfKey(ident));
-
-        if (info.rates.indexOfKey(ident) < 0) {
-            info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
-            if (info.rates.size() == 1) {
-                actuateHardware = true;
-            }
-        } else {
-            // sensor was already activated for this ident
-        }
-    } else {
-        Mutex::Autolock _l(mLock);
-        ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
-                info.rates.indexOfKey(ident));
-
-        ssize_t idx = info.rates.removeItem(ident);
-        if (idx >= 0) {
-            if (info.rates.size() == 0) {
-                actuateHardware = true;
-            }
-        } else {
-            // sensor wasn't enabled for this ident
-        }
-    }
-
-    if (actuateHardware) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w");
-
-        err = mSensorDevice->activate(mSensorDevice, handle, enabled);
-        if (enabled) {
-            ALOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
-            if (err == 0) {
-                BatteryService::getInstance().enableSensor(handle);
-            }
-        } else {
-            if (err == 0) {
-                BatteryService::getInstance().disableSensor(handle);
-            }
-        }
-    }
-
-    { // scope for the lock
-        Mutex::Autolock _l(mLock);
-        nsecs_t ns = info.selectDelay();
-        mSensorDevice->setDelay(mSensorDevice, handle, ns);
-    }
-
-    return err;
-}
-
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
-{
-    if (!mSensorDevice) return NO_INIT;
-    Mutex::Autolock _l(mLock);
-    Info& info( mActivationCount.editValueFor(handle) );
-    status_t err = info.setDelayForIdent(ident, ns);
-    if (err < 0) return err;
-    ns = info.selectDelay();
-    return mSensorDevice->setDelay(mSensorDevice, handle, ns);
-}
-
-// ---------------------------------------------------------------------------
-
-status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
-{
-    ssize_t index = rates.indexOfKey(ident);
-    if (index < 0) {
-        ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)",
-                ident, ns, strerror(-index));
-        return BAD_INDEX;
-    }
-    rates.editValueAt(index) = ns;
-    return NO_ERROR;
-}
-
-nsecs_t SensorDevice::Info::selectDelay()
-{
-    nsecs_t ns = rates.valueAt(0);
-    for (size_t i=1 ; i<rates.size() ; i++) {
-        nsecs_t cur = rates.valueAt(i);
-        if (cur < ns) {
-            ns = cur;
-        }
-    }
-    delay = ns;
-    return ns;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
deleted file mode 100644
index 728b6cb..0000000
--- a/services/sensorservice/SensorDevice.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSOR_DEVICE_H
-#define ANDROID_SENSOR_DEVICE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/KeyedVector.h>
-#include <utils/Singleton.h>
-#include <utils/String8.h>
-
-#include <gui/Sensor.h>
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-static const nsecs_t DEFAULT_EVENTS_PERIOD = 200000000; //    5 Hz
-
-class SensorDevice : public Singleton<SensorDevice> {
-    friend class Singleton<SensorDevice>;
-    struct sensors_poll_device_t* mSensorDevice;
-    struct sensors_module_t* mSensorModule;
-    mutable Mutex mLock; // protect mActivationCount[].rates
-    // fixed-size array after construction
-    struct Info {
-        Info() : delay(0) { }
-        KeyedVector<void*, nsecs_t> rates;
-        nsecs_t delay;
-        status_t setDelayForIdent(void* ident, int64_t ns);
-        nsecs_t selectDelay();
-    };
-    DefaultKeyedVector<int, Info> mActivationCount;
-
-    SensorDevice();
-public:
-    ssize_t getSensorList(sensor_t const** list);
-    status_t initCheck() const;
-    ssize_t poll(sensors_event_t* buffer, size_t count);
-    status_t activate(void* ident, int handle, int enabled);
-    status_t setDelay(void* ident, int handle, int64_t ns);
-    void dump(String8& result, char* buffer, size_t SIZE);
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_DEVICE_H
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
deleted file mode 100644
index d23906d..0000000
--- a/services/sensorservice/SensorFusion.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-#include "SensorService.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorFusion)
-
-SensorFusion::SensorFusion()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mEnabled(false), mGyroTime(0)
-{
-    sensor_t const* list;
-    ssize_t count = mSensorDevice.getSensorList(&list);
-    if (count > 0) {
-        for (size_t i=0 ; i<size_t(count) ; i++) {
-            if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
-                mAcc = Sensor(list + i);
-            }
-            if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
-                mMag = Sensor(list + i);
-            }
-            if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
-                mGyro = Sensor(list + i);
-                // 200 Hz for gyro events is a good compromise between precision
-                // and power/cpu usage.
-                mGyroRate = 200;
-                mTargetDelayNs = 1000000000LL/mGyroRate;
-            }
-        }
-        mFusion.init();
-    }
-}
-
-void SensorFusion::process(const sensors_event_t& event) {
-    if (event.type == SENSOR_TYPE_GYROSCOPE) {
-        if (mGyroTime != 0) {
-            const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
-            const float freq = 1 / dT;
-            if (freq >= 100 && freq<1000) { // filter values obviously wrong
-                const float alpha = 1 / (1 + dT); // 1s time-constant
-                mGyroRate = freq + (mGyroRate - freq)*alpha;
-            }
-        }
-        mGyroTime = event.timestamp;
-        mFusion.handleGyro(vec3_t(event.data), 1.0f/mGyroRate);
-    } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
-        const vec3_t mag(event.data);
-        mFusion.handleMag(mag);
-    } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        const vec3_t acc(event.data);
-        mFusion.handleAcc(acc);
-        mAttitude = mFusion.getAttitude();
-    }
-}
-
-template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
-template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
-
-status_t SensorFusion::activate(void* ident, bool enabled) {
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-            "SensorFusion::activate(ident=%p, enabled=%d)",
-            ident, enabled);
-
-    const ssize_t idx = mClients.indexOf(ident);
-    if (enabled) {
-        if (idx < 0) {
-            mClients.add(ident);
-        }
-    } else {
-        if (idx >= 0) {
-            mClients.removeItemsAt(idx);
-        }
-    }
-
-    mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
-    mSensorDevice.activate(ident, mMag.getHandle(), enabled);
-    mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
-
-    const bool newState = mClients.size() != 0;
-    if (newState != mEnabled) {
-        mEnabled = newState;
-        if (newState) {
-            mFusion.init();
-            mGyroTime = 0;
-        }
-    }
-    return NO_ERROR;
-}
-
-status_t SensorFusion::setDelay(void* ident, int64_t ns) {
-    mSensorDevice.setDelay(ident, mAcc.getHandle(), ns);
-    mSensorDevice.setDelay(ident, mMag.getHandle(), ms2ns(20));
-    mSensorDevice.setDelay(ident, mGyro.getHandle(), mTargetDelayNs);
-    return NO_ERROR;
-}
-
-
-float SensorFusion::getPowerUsage() const {
-    float power =   mAcc.getPowerUsage() +
-                    mMag.getPowerUsage() +
-                    mGyro.getPowerUsage();
-    return power;
-}
-
-int32_t SensorFusion::getMinDelay() const {
-    return mAcc.getMinDelay();
-}
-
-void SensorFusion::dump(String8& result, char* buffer, size_t SIZE) {
-    const Fusion& fusion(mFusion);
-    snprintf(buffer, SIZE, "9-axis fusion %s (%d clients), gyro-rate=%7.2fHz, "
-            "q=< %g, %g, %g, %g > (%g), "
-            "b=< %g, %g, %g >\n",
-            mEnabled ? "enabled" : "disabled",
-            mClients.size(),
-            mGyroRate,
-            fusion.getAttitude().x,
-            fusion.getAttitude().y,
-            fusion.getAttitude().z,
-            fusion.getAttitude().w,
-            length(fusion.getAttitude()),
-            fusion.getBias().x,
-            fusion.getBias().y,
-            fusion.getBias().z);
-    result.append(buffer);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
deleted file mode 100644
index 4c99bcb..0000000
--- a/services/sensorservice/SensorFusion.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSOR_FUSION_H
-#define ANDROID_SENSOR_FUSION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/SortedVector.h>
-#include <utils/Singleton.h>
-#include <utils/String8.h>
-
-#include <gui/Sensor.h>
-
-#include "Fusion.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-
-class SensorFusion : public Singleton<SensorFusion> {
-    friend class Singleton<SensorFusion>;
-
-    SensorDevice& mSensorDevice;
-    Sensor mAcc;
-    Sensor mMag;
-    Sensor mGyro;
-    Fusion mFusion;
-    bool mEnabled;
-    float mGyroRate;
-    nsecs_t mTargetDelayNs;
-    nsecs_t mGyroTime;
-    vec4_t mAttitude;
-    SortedVector<void*> mClients;
-
-    SensorFusion();
-
-public:
-    void process(const sensors_event_t& event);
-
-    bool isEnabled() const { return mEnabled; }
-    bool hasEstimate() const { return mFusion.hasEstimate(); }
-    mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
-    vec4_t getAttitude() const { return mAttitude; }
-    vec3_t getGyroBias() const { return mFusion.getBias(); }
-    float getEstimatedRate() const { return mGyroRate; }
-
-    status_t activate(void* ident, bool enabled);
-    status_t setDelay(void* ident, int64_t ns);
-
-    float getPowerUsage() const;
-    int32_t getMinDelay() const;
-
-    void dump(String8& result, char* buffer, size_t SIZE);
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_FUSION_H
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
deleted file mode 100644
index 468aa61..0000000
--- a/services/sensorservice/SensorInterface.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <cutils/log.h>
-
-#include "SensorInterface.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-SensorInterface::~SensorInterface()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-HardwareSensor::HardwareSensor(const sensor_t& sensor)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensor(&sensor)
-{
-    ALOGI("%s", sensor.name);
-}
-
-HardwareSensor::~HardwareSensor() {
-}
-
-bool HardwareSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event) {
-    *outEvent = event;
-    return true;
-}
-
-status_t HardwareSensor::activate(void* ident, bool enabled) {
-    return mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
-}
-
-status_t HardwareSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorDevice.setDelay(ident, handle, ns);
-}
-
-Sensor HardwareSensor::getSensor() const {
-    return mSensor;
-}
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
deleted file mode 100644
index fb357d7..0000000
--- a/services/sensorservice/SensorInterface.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSOR_INTERFACE_H
-#define ANDROID_SENSOR_INTERFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorDevice.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorInterface {
-public:
-    virtual ~SensorInterface();
-
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event) = 0;
-
-    virtual status_t activate(void* ident, bool enabled) = 0;
-    virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
-    virtual Sensor getSensor() const = 0;
-    virtual bool isVirtual() const = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class HardwareSensor : public SensorInterface
-{
-    SensorDevice& mSensorDevice;
-    Sensor mSensor;
-
-public:
-    HardwareSensor(const sensor_t& sensor);
-
-    virtual ~HardwareSensor();
-
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return false; }
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_INTERFACE_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
deleted file mode 100644
index 9e5e84b..0000000
--- a/services/sensorservice/SensorService.cpp
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <cutils/properties.h>
-
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Singleton.h>
-#include <utils/String16.h>
-
-#include <binder/BinderService.h>
-#include <binder/IServiceManager.h>
-#include <binder/PermissionCache.h>
-
-#include <gui/ISensorServer.h>
-#include <gui/ISensorEventConnection.h>
-#include <gui/SensorEventQueue.h>
-
-#include <hardware/sensors.h>
-
-#include "CorrectedGyroSensor.h"
-#include "GravitySensor.h"
-#include "LinearAccelerationSensor.h"
-#include "OrientationSensor.h"
-#include "RotationVectorSensor.h"
-#include "SensorFusion.h"
-#include "SensorService.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-/*
- * Notes:
- *
- * - what about a gyro-corrected magnetic-field sensor?
- * - run mag sensor from time to time to force calibration
- * - gravity sensor length is wrong (=> drift in linear-acc sensor)
- *
- */
-
-SensorService::SensorService()
-    : mInitCheck(NO_INIT)
-{
-}
-
-void SensorService::onFirstRef()
-{
-    ALOGD("nuSensorService starting...");
-
-    SensorDevice& dev(SensorDevice::getInstance());
-
-    if (dev.initCheck() == NO_ERROR) {
-        sensor_t const* list;
-        ssize_t count = dev.getSensorList(&list);
-        if (count > 0) {
-            ssize_t orientationIndex = -1;
-            bool hasGyro = false;
-            uint32_t virtualSensorsNeeds =
-                    (1<<SENSOR_TYPE_GRAVITY) |
-                    (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
-                    (1<<SENSOR_TYPE_ROTATION_VECTOR);
-
-            mLastEventSeen.setCapacity(count);
-            for (ssize_t i=0 ; i<count ; i++) {
-                registerSensor( new HardwareSensor(list[i]) );
-                switch (list[i].type) {
-                    case SENSOR_TYPE_ORIENTATION:
-                        orientationIndex = i;
-                        break;
-                    case SENSOR_TYPE_GYROSCOPE:
-                        hasGyro = true;
-                        break;
-                    case SENSOR_TYPE_GRAVITY:
-                    case SENSOR_TYPE_LINEAR_ACCELERATION:
-                    case SENSOR_TYPE_ROTATION_VECTOR:
-                        virtualSensorsNeeds &= ~(1<<list[i].type);
-                        break;
-                }
-            }
-
-            // it's safe to instantiate the SensorFusion object here
-            // (it wants to be instantiated after h/w sensors have been
-            // registered)
-            const SensorFusion& fusion(SensorFusion::getInstance());
-
-            if (hasGyro) {
-                // Always instantiate Android's virtual sensors. Since they are
-                // instantiated behind sensors from the HAL, they won't
-                // interfere with applications, unless they looks specifically
-                // for them (by name).
-
-                registerVirtualSensor( new RotationVectorSensor() );
-                registerVirtualSensor( new GravitySensor(list, count) );
-                registerVirtualSensor( new LinearAccelerationSensor(list, count) );
-
-                // these are optional
-                registerVirtualSensor( new OrientationSensor() );
-                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
-
-                // virtual debugging sensors...
-                char value[PROPERTY_VALUE_MAX];
-                property_get("debug.sensors", value, "0");
-                if (atoi(value)) {
-                    registerVirtualSensor( new GyroDriftSensor() );
-                }
-            }
-
-            // build the sensor list returned to users
-            mUserSensorList = mSensorList;
-            if (hasGyro &&
-                    (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
-                // if we have the fancy sensor fusion, and it's not provided by the
-                // HAL, use our own (fused) orientation sensor by removing the
-                // HAL supplied one form the user list.
-                if (orientationIndex >= 0) {
-                    mUserSensorList.removeItemsAt(orientationIndex);
-                }
-            }
-
-            run("SensorService", PRIORITY_URGENT_DISPLAY);
-            mInitCheck = NO_ERROR;
-        }
-    }
-}
-
-void SensorService::registerSensor(SensorInterface* s)
-{
-    sensors_event_t event;
-    memset(&event, 0, sizeof(event));
-
-    const Sensor sensor(s->getSensor());
-    // add to the sensor list (returned to clients)
-    mSensorList.add(sensor);
-    // add to our handle->SensorInterface mapping
-    mSensorMap.add(sensor.getHandle(), s);
-    // create an entry in the mLastEventSeen array
-    mLastEventSeen.add(sensor.getHandle(), event);
-}
-
-void SensorService::registerVirtualSensor(SensorInterface* s)
-{
-    registerSensor(s);
-    mVirtualSensorList.add( s );
-}
-
-SensorService::~SensorService()
-{
-    for (size_t i=0 ; i<mSensorMap.size() ; i++)
-        delete mSensorMap.valueAt(i);
-}
-
-static const String16 sDump("android.permission.DUMP");
-
-status_t SensorService::dump(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 1024;
-    char buffer[SIZE];
-    String8 result;
-    if (!PermissionCache::checkCallingPermission(sDump)) {
-        snprintf(buffer, SIZE, "Permission Denial: "
-                "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
-                IPCThreadState::self()->getCallingPid(),
-                IPCThreadState::self()->getCallingUid());
-        result.append(buffer);
-    } else {
-        Mutex::Autolock _l(mLock);
-        snprintf(buffer, SIZE, "Sensor List:\n");
-        result.append(buffer);
-        for (size_t i=0 ; i<mSensorList.size() ; i++) {
-            const Sensor& s(mSensorList[i]);
-            const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
-            snprintf(buffer, SIZE,
-                    "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | "
-                    "last=<%5.1f,%5.1f,%5.1f>\n",
-                    s.getName().string(),
-                    s.getVendor().string(),
-                    s.getHandle(),
-                    s.getMinDelay() ? (1000000.0f / s.getMinDelay()) : 0.0f,
-                    e.data[0], e.data[1], e.data[2]);
-            result.append(buffer);
-        }
-        SensorFusion::getInstance().dump(result, buffer, SIZE);
-        SensorDevice::getInstance().dump(result, buffer, SIZE);
-
-        snprintf(buffer, SIZE, "%d active connections\n",
-                mActiveConnections.size());
-        result.append(buffer);
-        snprintf(buffer, SIZE, "Active sensors:\n");
-        result.append(buffer);
-        for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
-            int handle = mActiveSensors.keyAt(i);
-            snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n",
-                    getSensorName(handle).string(),
-                    handle,
-                    mActiveSensors.valueAt(i)->getNumConnections());
-            result.append(buffer);
-        }
-    }
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-bool SensorService::threadLoop()
-{
-    ALOGD("nuSensorService thread starting...");
-
-    const size_t numEventMax = 16;
-    const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();
-    sensors_event_t buffer[minBufferSize];
-    sensors_event_t scratch[minBufferSize];
-    SensorDevice& device(SensorDevice::getInstance());
-    const size_t vcount = mVirtualSensorList.size();
-
-    ssize_t count;
-    do {
-        count = device.poll(buffer, numEventMax);
-        if (count<0) {
-            ALOGE("sensor poll failed (%s)", strerror(-count));
-            break;
-        }
-
-        recordLastValue(buffer, count);
-
-        // handle virtual sensors
-        if (count && vcount) {
-            sensors_event_t const * const event = buffer;
-            const DefaultKeyedVector<int, SensorInterface*> virtualSensors(
-                    getActiveVirtualSensors());
-            const size_t activeVirtualSensorCount = virtualSensors.size();
-            if (activeVirtualSensorCount) {
-                size_t k = 0;
-                SensorFusion& fusion(SensorFusion::getInstance());
-                if (fusion.isEnabled()) {
-                    for (size_t i=0 ; i<size_t(count) ; i++) {
-                        fusion.process(event[i]);
-                    }
-                }
-                for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
-                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
-                        if (count + k >= minBufferSize) {
-                            ALOGE("buffer too small to hold all events: "
-                                    "count=%u, k=%u, size=%u",
-                                    count, k, minBufferSize);
-                            break;
-                        }
-                        sensors_event_t out;
-                        SensorInterface* si = virtualSensors.valueAt(j);
-                        if (si->process(&out, event[i])) {
-                            buffer[count + k] = out;
-                            k++;
-                        }
-                    }
-                }
-                if (k) {
-                    // record the last synthesized values
-                    recordLastValue(&buffer[count], k);
-                    count += k;
-                    // sort the buffer by time-stamps
-                    sortEventBuffer(buffer, count);
-                }
-            }
-        }
-
-        // send our events to clients...
-        const SortedVector< wp<SensorEventConnection> > activeConnections(
-                getActiveConnections());
-        size_t numConnections = activeConnections.size();
-        for (size_t i=0 ; i<numConnections ; i++) {
-            sp<SensorEventConnection> connection(
-                    activeConnections[i].promote());
-            if (connection != 0) {
-                connection->sendEvents(buffer, count, scratch);
-            }
-        }
-    } while (count >= 0 || Thread::exitPending());
-
-    ALOGW("Exiting SensorService::threadLoop => aborting...");
-    abort();
-    return false;
-}
-
-void SensorService::recordLastValue(
-        sensors_event_t const * buffer, size_t count)
-{
-    Mutex::Autolock _l(mLock);
-
-    // record the last event for each sensor
-    int32_t prev = buffer[0].sensor;
-    for (size_t i=1 ; i<count ; i++) {
-        // record the last event of each sensor type in this buffer
-        int32_t curr = buffer[i].sensor;
-        if (curr != prev) {
-            mLastEventSeen.editValueFor(prev) = buffer[i-1];
-            prev = curr;
-        }
-    }
-    mLastEventSeen.editValueFor(prev) = buffer[count-1];
-}
-
-void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
-{
-    struct compar {
-        static int cmp(void const* lhs, void const* rhs) {
-            sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
-            sensors_event_t const* r = static_cast<sensors_event_t const*>(rhs);
-            return l->timestamp - r->timestamp;
-        }
-    };
-    qsort(buffer, count, sizeof(sensors_event_t), compar::cmp);
-}
-
-SortedVector< wp<SensorService::SensorEventConnection> >
-SensorService::getActiveConnections() const
-{
-    Mutex::Autolock _l(mLock);
-    return mActiveConnections;
-}
-
-DefaultKeyedVector<int, SensorInterface*>
-SensorService::getActiveVirtualSensors() const
-{
-    Mutex::Autolock _l(mLock);
-    return mActiveVirtualSensors;
-}
-
-String8 SensorService::getSensorName(int handle) const {
-    size_t count = mUserSensorList.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const Sensor& sensor(mUserSensorList[i]);
-        if (sensor.getHandle() == handle) {
-            return sensor.getName();
-        }
-    }
-    String8 result("unknown");
-    return result;
-}
-
-Vector<Sensor> SensorService::getSensorList()
-{
-    return mUserSensorList;
-}
-
-sp<ISensorEventConnection> SensorService::createSensorEventConnection()
-{
-    sp<SensorEventConnection> result(new SensorEventConnection(this));
-    return result;
-}
-
-void SensorService::cleanupConnection(SensorEventConnection* c)
-{
-    Mutex::Autolock _l(mLock);
-    const wp<SensorEventConnection> connection(c);
-    size_t size = mActiveSensors.size();
-    ALOGD_IF(DEBUG_CONNECTIONS, "%d active sensors", size);
-    for (size_t i=0 ; i<size ; ) {
-        int handle = mActiveSensors.keyAt(i);
-        if (c->hasSensor(handle)) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "%i: disabling handle=0x%08x", i, handle);
-            SensorInterface* sensor = mSensorMap.valueFor( handle );
-            ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
-            if (sensor) {
-                sensor->activate(c, false);
-            }
-        }
-        SensorRecord* rec = mActiveSensors.valueAt(i);
-        ALOGE_IF(!rec, "mActiveSensors[%d] is null (handle=0x%08x)!", i, handle);
-        ALOGD_IF(DEBUG_CONNECTIONS,
-                "removing connection %p for sensor[%d].handle=0x%08x",
-                c, i, handle);
-
-        if (rec && rec->removeConnection(connection)) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
-            mActiveSensors.removeItemsAt(i, 1);
-            mActiveVirtualSensors.removeItem(handle);
-            delete rec;
-            size--;
-        } else {
-            i++;
-        }
-    }
-    mActiveConnections.remove(connection);
-}
-
-status_t SensorService::enable(const sp<SensorEventConnection>& connection,
-        int handle)
-{
-    if (mInitCheck != NO_ERROR)
-        return mInitCheck;
-
-    Mutex::Autolock _l(mLock);
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);
-    if (err == NO_ERROR) {
-        SensorRecord* rec = mActiveSensors.valueFor(handle);
-        if (rec == 0) {
-            rec = new SensorRecord(connection);
-            mActiveSensors.add(handle, rec);
-            if (sensor->isVirtual()) {
-                mActiveVirtualSensors.add(handle, sensor);
-            }
-        } else {
-            if (rec->addConnection(connection)) {
-                // this sensor is already activated, but we are adding a
-                // connection that uses it. Immediately send down the last
-                // known value of the requested sensor if it's not a
-                // "continuous" sensor.
-                if (sensor->getSensor().getMinDelay() == 0) {
-                    sensors_event_t scratch;
-                    sensors_event_t& event(mLastEventSeen.editValueFor(handle));
-                    if (event.version == sizeof(sensors_event_t)) {
-                        connection->sendEvents(&event, 1);
-                    }
-                }
-            }
-        }
-        if (err == NO_ERROR) {
-            // connection now active
-            if (connection->addSensor(handle)) {
-                // the sensor was added (which means it wasn't already there)
-                // so, see if this connection becomes active
-                if (mActiveConnections.indexOf(connection) < 0) {
-                    mActiveConnections.add(connection);
-                }
-            }
-        }
-    }
-    return err;
-}
-
-status_t SensorService::disable(const sp<SensorEventConnection>& connection,
-        int handle)
-{
-    if (mInitCheck != NO_ERROR)
-        return mInitCheck;
-
-    status_t err = NO_ERROR;
-    Mutex::Autolock _l(mLock);
-    SensorRecord* rec = mActiveSensors.valueFor(handle);
-    if (rec) {
-        // see if this connection becomes inactive
-        connection->removeSensor(handle);
-        if (connection->hasAnySensor() == false) {
-            mActiveConnections.remove(connection);
-        }
-        // see if this sensor becomes inactive
-        if (rec->removeConnection(connection)) {
-            mActiveSensors.removeItem(handle);
-            mActiveVirtualSensors.removeItem(handle);
-            delete rec;
-        }
-        SensorInterface* sensor = mSensorMap.valueFor(handle);
-        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
-    }
-    return err;
-}
-
-status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
-        int handle, nsecs_t ns)
-{
-    if (mInitCheck != NO_ERROR)
-        return mInitCheck;
-
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    if (!sensor)
-        return BAD_VALUE;
-
-    if (ns < 0)
-        return BAD_VALUE;
-
-    nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
-    if (ns < minDelayNs) {
-        ns = minDelayNs;
-    }
-
-    if (ns < MINIMUM_EVENTS_PERIOD)
-        ns = MINIMUM_EVENTS_PERIOD;
-
-    return sensor->setDelay(connection.get(), handle, ns);
-}
-
-// ---------------------------------------------------------------------------
-
-SensorService::SensorRecord::SensorRecord(
-        const sp<SensorEventConnection>& connection)
-{
-    mConnections.add(connection);
-}
-
-bool SensorService::SensorRecord::addConnection(
-        const sp<SensorEventConnection>& connection)
-{
-    if (mConnections.indexOf(connection) < 0) {
-        mConnections.add(connection);
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorRecord::removeConnection(
-        const wp<SensorEventConnection>& connection)
-{
-    ssize_t index = mConnections.indexOf(connection);
-    if (index >= 0) {
-        mConnections.removeItemsAt(index, 1);
-    }
-    return mConnections.size() ? false : true;
-}
-
-// ---------------------------------------------------------------------------
-
-SensorService::SensorEventConnection::SensorEventConnection(
-        const sp<SensorService>& service)
-    : mService(service), mChannel(new BitTube())
-{
-}
-
-SensorService::SensorEventConnection::~SensorEventConnection()
-{
-    ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
-    mService->cleanupConnection(this);
-}
-
-void SensorService::SensorEventConnection::onFirstRef()
-{
-}
-
-bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.indexOf(handle) <= 0) {
-        mSensorInfo.add(handle);
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.remove(handle) >= 0) {
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.indexOf(handle) >= 0;
-}
-
-bool SensorService::SensorEventConnection::hasAnySensor() const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.size() ? true : false;
-}
-
-status_t SensorService::SensorEventConnection::sendEvents(
-        sensors_event_t const* buffer, size_t numEvents,
-        sensors_event_t* scratch)
-{
-    // filter out events not for this connection
-    size_t count = 0;
-    if (scratch) {
-        Mutex::Autolock _l(mConnectionLock);
-        size_t i=0;
-        while (i<numEvents) {
-            const int32_t curr = buffer[i].sensor;
-            if (mSensorInfo.indexOf(curr) >= 0) {
-                do {
-                    scratch[count++] = buffer[i++];
-                } while ((i<numEvents) && (buffer[i].sensor == curr));
-            } else {
-                i++;
-            }
-        }
-    } else {
-        scratch = const_cast<sensors_event_t *>(buffer);
-        count = numEvents;
-    }
-
-    // NOTE: ASensorEvent and sensors_event_t are the same type
-    ssize_t size = SensorEventQueue::write(mChannel,
-            reinterpret_cast<ASensorEvent const*>(scratch), count);
-    if (size == -EAGAIN) {
-        // the destination doesn't accept events anymore, it's probably
-        // full. For now, we just drop the events on the floor.
-        //ALOGW("dropping %d events on the floor", count);
-        return size;
-    }
-
-    return size < 0 ? status_t(size) : status_t(NO_ERROR);
-}
-
-sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
-{
-    return mChannel;
-}
-
-status_t SensorService::SensorEventConnection::enableDisable(
-        int handle, bool enabled)
-{
-    status_t err;
-    if (enabled) {
-        err = mService->enable(this, handle);
-    } else {
-        err = mService->disable(this, handle);
-    }
-    return err;
-}
-
-status_t SensorService::SensorEventConnection::setEventRate(
-        int handle, nsecs_t ns)
-{
-    return mService->setEventRate(this, handle, ns);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
deleted file mode 100644
index e357f96..0000000
--- a/services/sensorservice/SensorService.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSOR_SERVICE_H
-#define ANDROID_SENSOR_SERVICE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/RefBase.h>
-
-#include <binder/BinderService.h>
-
-#include <gui/Sensor.h>
-#include <gui/BitTube.h>
-#include <gui/ISensorServer.h>
-#include <gui/ISensorEventConnection.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-
-#define DEBUG_CONNECTIONS   false
-
-struct sensors_poll_device_t;
-struct sensors_module_t;
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorService :
-        public BinderService<SensorService>,
-        public BnSensorServer,
-        protected Thread
-{
-   friend class BinderService<SensorService>;
-
-   static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
-
-            SensorService();
-    virtual ~SensorService();
-
-    virtual void onFirstRef();
-
-    // Thread interface
-    virtual bool threadLoop();
-
-    // ISensorServer interface
-    virtual Vector<Sensor> getSensorList();
-    virtual sp<ISensorEventConnection> createSensorEventConnection();
-    virtual status_t dump(int fd, const Vector<String16>& args);
-
-
-    class SensorEventConnection : public BnSensorEventConnection {
-        virtual ~SensorEventConnection();
-        virtual void onFirstRef();
-        virtual sp<BitTube> getSensorChannel() const;
-        virtual status_t enableDisable(int handle, bool enabled);
-        virtual status_t setEventRate(int handle, nsecs_t ns);
-
-        sp<SensorService> const mService;
-        sp<BitTube> const mChannel;
-        mutable Mutex mConnectionLock;
-
-        // protected by SensorService::mLock
-        SortedVector<int> mSensorInfo;
-
-    public:
-        SensorEventConnection(const sp<SensorService>& service);
-
-        status_t sendEvents(sensors_event_t const* buffer, size_t count,
-                sensors_event_t* scratch = NULL);
-        bool hasSensor(int32_t handle) const;
-        bool hasAnySensor() const;
-        bool addSensor(int32_t handle);
-        bool removeSensor(int32_t handle);
-    };
-
-    class SensorRecord {
-        SortedVector< wp<SensorEventConnection> > mConnections;
-    public:
-        SensorRecord(const sp<SensorEventConnection>& connection);
-        bool addConnection(const sp<SensorEventConnection>& connection);
-        bool removeConnection(const wp<SensorEventConnection>& connection);
-        size_t getNumConnections() const { return mConnections.size(); }
-    };
-
-    SortedVector< wp<SensorEventConnection> > getActiveConnections() const;
-    DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
-
-    String8 getSensorName(int handle) const;
-    void recordLastValue(sensors_event_t const * buffer, size_t count);
-    static void sortEventBuffer(sensors_event_t* buffer, size_t count);
-    void registerSensor(SensorInterface* sensor);
-    void registerVirtualSensor(SensorInterface* sensor);
-
-    // constants
-    Vector<Sensor> mSensorList;
-    Vector<Sensor> mUserSensorList;
-    DefaultKeyedVector<int, SensorInterface*> mSensorMap;
-    Vector<SensorInterface *> mVirtualSensorList;
-    status_t mInitCheck;
-
-    // protected by mLock
-    mutable Mutex mLock;
-    DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
-    DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
-    SortedVector< wp<SensorEventConnection> > mActiveConnections;
-
-    // The size of this vector is constant, only the items are mutable
-    KeyedVector<int32_t, sensors_event_t> mLastEventSeen;
-
-public:
-    static char const* getServiceName() { return "sensorservice"; }
-
-    void cleanupConnection(SensorEventConnection* connection);
-    status_t enable(const sp<SensorEventConnection>& connection, int handle);
-    status_t disable(const sp<SensorEventConnection>& connection, int handle);
-    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns);
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_SERVICE_H
diff --git a/services/sensorservice/mat.h b/services/sensorservice/mat.h
deleted file mode 100644
index a76fc91..0000000
--- a/services/sensorservice/mat.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MAT_H
-#define ANDROID_MAT_H
-
-#include "vec.h"
-#include "traits.h"
-
-// -----------------------------------------------------------------------
-
-namespace android {
-
-template <typename TYPE, size_t C, size_t R>
-class mat;
-
-namespace helpers {
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R>& doAssign(
-        mat<TYPE, C, R>& lhs,
-        typename TypeTraits<TYPE>::ParameterType rhs) {
-    for (size_t i=0 ; i<C ; i++)
-        for (size_t j=0 ; j<R ; j++)
-            lhs[i][j] = (i==j) ? rhs : 0;
-    return lhs;
-}
-
-template <typename TYPE, size_t C, size_t R, size_t D>
-mat<TYPE, C, R> PURE doMul(
-        const mat<TYPE, D, R>& lhs,
-        const mat<TYPE, C, D>& rhs)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            TYPE v(0);
-            for (size_t k=0 ; k<D ; k++) {
-                v += lhs[k][r] * rhs[c][k];
-            }
-            res[c][r] = v;
-        }
-    }
-    return res;
-}
-
-template <typename TYPE, size_t R, size_t D>
-vec<TYPE, R> PURE doMul(
-        const mat<TYPE, D, R>& lhs,
-        const vec<TYPE, D>& rhs)
-{
-    vec<TYPE, R> res;
-    for (size_t r=0 ; r<R ; r++) {
-        TYPE v(0);
-        for (size_t k=0 ; k<D ; k++) {
-            v += lhs[k][r] * rhs[k];
-        }
-        res[r] = v;
-    }
-    return res;
-}
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R> PURE doMul(
-        const vec<TYPE, R>& lhs,
-        const mat<TYPE, C, 1>& rhs)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            res[c][r] = lhs[r] * rhs[c][0];
-        }
-    }
-    return res;
-}
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R> PURE doMul(
-        const mat<TYPE, C, R>& rhs,
-        typename TypeTraits<TYPE>::ParameterType v)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            res[c][r] = rhs[c][r] * v;
-        }
-    }
-    return res;
-}
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R> PURE doMul(
-        typename TypeTraits<TYPE>::ParameterType v,
-        const mat<TYPE, C, R>& rhs)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            res[c][r] = v * rhs[c][r];
-        }
-    }
-    return res;
-}
-
-
-}; // namespace helpers
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t C, size_t R>
-class mat : public vec< vec<TYPE, R>, C > {
-    typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
-    typedef vec< vec<TYPE, R>, C > base;
-public:
-    // STL-like interface.
-    typedef TYPE value_type;
-    typedef TYPE& reference;
-    typedef TYPE const& const_reference;
-    typedef size_t size_type;
-    size_type size() const { return R*C; }
-    enum { ROWS = R, COLS = C };
-
-
-    // -----------------------------------------------------------------------
-    // default constructors
-
-    mat() { }
-    mat(const mat& rhs)  : base(rhs) { }
-    mat(const base& rhs) : base(rhs) { }
-
-    // -----------------------------------------------------------------------
-    // conversion constructors
-
-    // sets the diagonal to the value, off-diagonal to zero
-    mat(pTYPE rhs) {
-        helpers::doAssign(*this, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // Assignment
-
-    mat& operator=(const mat& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    mat& operator=(const base& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    mat& operator=(pTYPE rhs) {
-        return helpers::doAssign(*this, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // non-member function declaration and definition
-
-    friend inline mat PURE operator + (const mat& lhs, const mat& rhs) {
-        return helpers::doAdd(
-                static_cast<const base&>(lhs),
-                static_cast<const base&>(rhs));
-    }
-    friend inline mat PURE operator - (const mat& lhs, const mat& rhs) {
-        return helpers::doSub(
-                static_cast<const base&>(lhs),
-                static_cast<const base&>(rhs));
-    }
-
-    // matrix*matrix
-    template <size_t D>
-    friend mat PURE operator * (
-            const mat<TYPE, D, R>& lhs,
-            const mat<TYPE, C, D>& rhs) {
-        return helpers::doMul(lhs, rhs);
-    }
-
-    // matrix*vector
-    friend vec<TYPE, R> PURE operator * (
-            const mat& lhs, const vec<TYPE, C>& rhs) {
-        return helpers::doMul(lhs, rhs);
-    }
-
-    // vector*matrix
-    friend mat PURE operator * (
-            const vec<TYPE, R>& lhs, const mat<TYPE, C, 1>& rhs) {
-        return helpers::doMul(lhs, rhs);
-    }
-
-    // matrix*scalar
-    friend inline mat PURE operator * (const mat& lhs, pTYPE v) {
-        return helpers::doMul(lhs, v);
-    }
-
-    // scalar*matrix
-    friend inline mat PURE operator * (pTYPE v, const mat& rhs) {
-        return helpers::doMul(v, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // streaming operator to set the columns of the matrix:
-    // example:
-    //    mat33_t m;
-    //    m << v0 << v1 << v2;
-
-    // column_builder<> stores the matrix and knows which column to set
-    template<size_t PREV_COLUMN>
-    struct column_builder {
-        mat& matrix;
-        column_builder(mat& matrix) : matrix(matrix) { }
-    };
-
-    // operator << is not a method of column_builder<> so we can
-    // overload it for unauthorized values (partial specialization
-    // not allowed in class-scope).
-    // we just set the column and return the next column_builder<>
-    template<size_t PREV_COLUMN>
-    friend column_builder<PREV_COLUMN+1> operator << (
-            const column_builder<PREV_COLUMN>& lhs,
-            const vec<TYPE, R>& rhs) {
-        lhs.matrix[PREV_COLUMN+1] = rhs;
-        return column_builder<PREV_COLUMN+1>(lhs.matrix);
-    }
-
-    // we return void here so we get a compile-time error if the
-    // user tries to set too many columns
-    friend void operator << (
-            const column_builder<C-2>& lhs,
-            const vec<TYPE, R>& rhs) {
-        lhs.matrix[C-1] = rhs;
-    }
-
-    // this is where the process starts. we set the first columns and
-    // return the next column_builder<>
-    column_builder<0> operator << (const vec<TYPE, R>& rhs) {
-        (*this)[0] = rhs;
-        return column_builder<0>(*this);
-    }
-};
-
-// Specialize column matrix so they're exactly equivalent to a vector
-template <typename TYPE, size_t R>
-class mat<TYPE, 1, R> : public vec<TYPE, R> {
-    typedef vec<TYPE, R> base;
-public:
-    // STL-like interface.
-    typedef TYPE value_type;
-    typedef TYPE& reference;
-    typedef TYPE const& const_reference;
-    typedef size_t size_type;
-    size_type size() const { return R; }
-    enum { ROWS = R, COLS = 1 };
-
-    mat() { }
-    mat(const base& rhs) : base(rhs) { }
-    mat(const mat& rhs) : base(rhs) { }
-    mat(const TYPE& rhs) { helpers::doAssign(*this, rhs); }
-    mat& operator=(const mat& rhs) { base::operator=(rhs); return *this; }
-    mat& operator=(const base& rhs) { base::operator=(rhs); return *this; }
-    mat& operator=(const TYPE& rhs) { return helpers::doAssign(*this, rhs); }
-    // we only have one column, so ignore the index
-    const base& operator[](size_t) const { return *this; }
-    base& operator[](size_t) { return *this; }
-    void operator << (const vec<TYPE, R>& rhs) { base::operator[](0) = rhs; }
-};
-
-// -----------------------------------------------------------------------
-// matrix functions
-
-// transpose. this handles matrices of matrices
-inline int     PURE transpose(int v)    { return v; }
-inline float   PURE transpose(float v)  { return v; }
-inline double  PURE transpose(double v) { return v; }
-
-// Transpose a matrix
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, R, C> PURE transpose(const mat<TYPE, C, R>& m) {
-    mat<TYPE, R, C> r;
-    for (size_t i=0 ; i<R ; i++)
-        for (size_t j=0 ; j<C ; j++)
-            r[i][j] = transpose(m[j][i]);
-    return r;
-}
-
-// Calculate the trace of a matrix
-template <typename TYPE, size_t C> static TYPE trace(const mat<TYPE, C, C>& m) {
-    TYPE t;
-    for (size_t i=0 ; i<C ; i++)
-        t += m[i][i];
-    return t;
-}
-
-// Test positive-semidefiniteness of a matrix
-template <typename TYPE, size_t C>
-static bool isPositiveSemidefinite(const mat<TYPE, C, C>& m, TYPE tolerance) {
-    for (size_t i=0 ; i<C ; i++)
-        if (m[i][i] < 0)
-            return false;
-
-    for (size_t i=0 ; i<C ; i++)
-      for (size_t j=i+1 ; j<C ; j++)
-          if (fabs(m[i][j] - m[j][i]) > tolerance)
-              return false;
-
-    return true;
-}
-
-// Transpose a vector
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-mat<TYPE, SIZE, 1> PURE transpose(const VEC<TYPE, SIZE>& v) {
-    mat<TYPE, SIZE, 1> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i][0] = transpose(v[i]);
-    return r;
-}
-
-// -----------------------------------------------------------------------
-// "dumb" matrix inversion
-template<typename T, size_t N>
-mat<T, N, N> PURE invert(const mat<T, N, N>& src) {
-    T t;
-    size_t swap;
-    mat<T, N, N> tmp(src);
-    mat<T, N, N> inverse(1);
-
-    for (size_t i=0 ; i<N ; i++) {
-        // look for largest element in column
-        swap = i;
-        for (size_t j=i+1 ; j<N ; j++) {
-            if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
-                swap = j;
-            }
-        }
-
-        if (swap != i) {
-            /* swap rows. */
-            for (size_t k=0 ; k<N ; k++) {
-                t = tmp[i][k];
-                tmp[i][k] = tmp[swap][k];
-                tmp[swap][k] = t;
-
-                t = inverse[i][k];
-                inverse[i][k] = inverse[swap][k];
-                inverse[swap][k] = t;
-            }
-        }
-
-        t = 1 / tmp[i][i];
-        for (size_t k=0 ; k<N ; k++) {
-            tmp[i][k] *= t;
-            inverse[i][k] *= t;
-        }
-        for (size_t j=0 ; j<N ; j++) {
-            if (j != i) {
-                t = tmp[j][i];
-                for (size_t k=0 ; k<N ; k++) {
-                    tmp[j][k] -= tmp[i][k] * t;
-                    inverse[j][k] -= inverse[i][k] * t;
-                }
-            }
-        }
-    }
-    return inverse;
-}
-
-// -----------------------------------------------------------------------
-
-typedef mat<float, 2, 2> mat22_t;
-typedef mat<float, 3, 3> mat33_t;
-typedef mat<float, 4, 4> mat44_t;
-
-// -----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /* ANDROID_MAT_H */
diff --git a/services/sensorservice/quat.h b/services/sensorservice/quat.h
deleted file mode 100644
index fea1afe..0000000
--- a/services/sensorservice/quat.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_QUAT_H
-#define ANDROID_QUAT_H
-
-#include <math.h>
-
-#include "vec.h"
-#include "mat.h"
-
-// -----------------------------------------------------------------------
-namespace android {
-// -----------------------------------------------------------------------
-
-template <typename TYPE>
-mat<TYPE, 3, 3> quatToMatrix(const vec<TYPE, 4>& q) {
-    mat<TYPE, 3, 3> R;
-    TYPE q0(q.w);
-    TYPE q1(q.x);
-    TYPE q2(q.y);
-    TYPE q3(q.z);
-    TYPE sq_q1 = 2 * q1 * q1;
-    TYPE sq_q2 = 2 * q2 * q2;
-    TYPE sq_q3 = 2 * q3 * q3;
-    TYPE q1_q2 = 2 * q1 * q2;
-    TYPE q3_q0 = 2 * q3 * q0;
-    TYPE q1_q3 = 2 * q1 * q3;
-    TYPE q2_q0 = 2 * q2 * q0;
-    TYPE q2_q3 = 2 * q2 * q3;
-    TYPE q1_q0 = 2 * q1 * q0;
-    R[0][0] = 1 - sq_q2 - sq_q3;
-    R[0][1] = q1_q2 - q3_q0;
-    R[0][2] = q1_q3 + q2_q0;
-    R[1][0] = q1_q2 + q3_q0;
-    R[1][1] = 1 - sq_q1 - sq_q3;
-    R[1][2] = q2_q3 - q1_q0;
-    R[2][0] = q1_q3 - q2_q0;
-    R[2][1] = q2_q3 + q1_q0;
-    R[2][2] = 1 - sq_q1 - sq_q2;
-    return R;
-}
-
-template <typename TYPE>
-vec<TYPE, 4> matrixToQuat(const mat<TYPE, 3, 3>& R) {
-    // matrix to quaternion
-
-    struct {
-        inline TYPE operator()(TYPE v) {
-            return v < 0 ? 0 : v;
-        }
-    } clamp;
-
-    vec<TYPE, 4> q;
-    const float Hx = R[0].x;
-    const float My = R[1].y;
-    const float Az = R[2].z;
-    q.x = sqrtf( clamp( Hx - My - Az + 1) * 0.25f );
-    q.y = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f );
-    q.z = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f );
-    q.w = sqrtf( clamp( Hx + My + Az + 1) * 0.25f );
-    q.x = copysignf(q.x, R[2].y - R[1].z);
-    q.y = copysignf(q.y, R[0].z - R[2].x);
-    q.z = copysignf(q.z, R[1].x - R[0].y);
-    // guaranteed to be unit-quaternion
-    return q;
-}
-
-template <typename TYPE>
-vec<TYPE, 4> normalize_quat(const vec<TYPE, 4>& q) {
-    vec<TYPE, 4> r(q);
-    if (r.w < 0) {
-        r = -r;
-    }
-    return normalize(r);
-}
-
-// -----------------------------------------------------------------------
-
-typedef vec4_t quat_t;
-
-// -----------------------------------------------------------------------
-}; // namespace android
-
-#endif /* ANDROID_QUAT_H */
diff --git a/services/sensorservice/tests/Android.mk b/services/sensorservice/tests/Android.mk
deleted file mode 100644
index 45296dd..0000000
--- a/services/sensorservice/tests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	sensorservicetest.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils libutils libui libgui
-
-LOCAL_MODULE:= test-sensorservice
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
deleted file mode 100644
index 1025fa8..0000000
--- a/services/sensorservice/tests/sensorservicetest.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/sensor.h>
-#include <gui/Sensor.h>
-#include <gui/SensorManager.h>
-#include <gui/SensorEventQueue.h>
-#include <utils/Looper.h>
-
-using namespace android;
-
-static nsecs_t sStartTime = 0;
-
-
-int receiver(int fd, int events, void* data)
-{
-    sp<SensorEventQueue> q((SensorEventQueue*)data);
-    ssize_t n;
-    ASensorEvent buffer[8];
-
-    static nsecs_t oldTimeStamp = 0;
-
-    while ((n = q->read(buffer, 8)) > 0) {
-        for (int i=0 ; i<n ; i++) {
-            float t;
-            if (oldTimeStamp) {
-                t = float(buffer[i].timestamp - oldTimeStamp) / s2ns(1);
-            } else {
-                t = float(buffer[i].timestamp - sStartTime) / s2ns(1);
-            }
-            oldTimeStamp = buffer[i].timestamp;
-
-            if (buffer[i].type == Sensor::TYPE_ACCELEROMETER) {
-                printf("%lld\t%8f\t%8f\t%8f\t%f\n",
-                        buffer[i].timestamp,
-                        buffer[i].data[0], buffer[i].data[1], buffer[i].data[2],
-                        1.0/t);
-            }
-
-        }
-    }
-    if (n<0 && n != -EAGAIN) {
-        printf("error reading events (%s)\n", strerror(-n));
-    }
-    return 1;
-}
-
-
-int main(int argc, char** argv)
-{
-    SensorManager& mgr(SensorManager::getInstance());
-
-    Sensor const* const* list;
-    ssize_t count = mgr.getSensorList(&list);
-    printf("numSensors=%d\n", int(count));
-
-    sp<SensorEventQueue> q = mgr.createEventQueue();
-    printf("queue=%p\n", q.get());
-
-    Sensor const* accelerometer = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
-    printf("accelerometer=%p (%s)\n",
-            accelerometer, accelerometer->getName().string());
-
-    sStartTime = systemTime();
-
-    q->enableSensor(accelerometer);
-
-    q->setEventRate(accelerometer, ms2ns(10));
-
-    sp<Looper> loop = new Looper(false);
-    loop->addFd(q->getFd(), 0, ALOOPER_EVENT_INPUT, receiver, q.get());
-
-    do {
-        //printf("about to poll...\n");
-        int32_t ret = loop->pollOnce(-1);
-        switch (ret) {
-            case ALOOPER_POLL_WAKE:
-                //("ALOOPER_POLL_WAKE\n");
-                break;
-            case ALOOPER_POLL_CALLBACK:
-                //("ALOOPER_POLL_CALLBACK\n");
-                break;
-            case ALOOPER_POLL_TIMEOUT:
-                printf("ALOOPER_POLL_TIMEOUT\n");
-                break;
-            case ALOOPER_POLL_ERROR:
-                printf("ALOOPER_POLL_TIMEOUT\n");
-                break;
-            default:
-                printf("ugh? poll returned %d\n", ret);
-                break;
-        }
-    } while (1);
-
-
-    return 0;
-}
diff --git a/services/sensorservice/traits.h b/services/sensorservice/traits.h
deleted file mode 100644
index da4c599..0000000
--- a/services/sensorservice/traits.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_TRAITS_H
-#define ANDROID_TRAITS_H
-
-// -----------------------------------------------------------------------
-// Typelists
-
-namespace android {
-
-// end-of-list marker
-class NullType {};
-
-// type-list node
-template <typename T, typename U>
-struct TypeList {
-    typedef T Head;
-    typedef U Tail;
-};
-
-// helpers to build typelists
-#define TYPELIST_1(T1) TypeList<T1, NullType>
-#define TYPELIST_2(T1, T2) TypeList<T1, TYPELIST_1(T2)>
-#define TYPELIST_3(T1, T2, T3) TypeList<T1, TYPELIST_2(T2, T3)>
-#define TYPELIST_4(T1, T2, T3, T4) TypeList<T1, TYPELIST_3(T2, T3, T4)>
-
-// typelists algorithms
-namespace TL {
-template <typename TList, typename T> struct IndexOf;
-
-template <typename T>
-struct IndexOf<NullType, T> {
-    enum { value = -1 };
-};
-
-template <typename T, typename Tail>
-struct IndexOf<TypeList<T, Tail>, T> {
-    enum { value = 0 };
-};
-
-template <typename Head, typename Tail, typename T>
-struct IndexOf<TypeList<Head, Tail>, T> {
-private:
-    enum { temp = IndexOf<Tail, T>::value };
-public:
-    enum { value = temp == -1 ? -1 : 1 + temp };
-};
-
-}; // namespace TL
-
-// type selection based on a boolean
-template <bool flag, typename T, typename U>
-struct Select {
-    typedef T Result;
-};
-template <typename T, typename U>
-struct Select<false, T, U> {
-    typedef U Result;
-};
-
-// -----------------------------------------------------------------------
-// Type traits
-
-template <typename T>
-class TypeTraits {
-    typedef TYPELIST_4(
-            unsigned char, unsigned short,
-            unsigned int, unsigned long int) UnsignedInts;
-
-    typedef TYPELIST_4(
-            signed char, signed short,
-            signed int, signed long int) SignedInts;
-
-    typedef TYPELIST_1(
-            bool) OtherInts;
-
-    typedef TYPELIST_3(
-            float, double, long double) Floats;
-
-    template<typename U> struct PointerTraits {
-        enum { result = false };
-        typedef NullType PointeeType;
-    };
-    template<typename U> struct PointerTraits<U*> {
-        enum { result = true };
-        typedef U PointeeType;
-    };
-
-public:
-    enum { isStdUnsignedInt = TL::IndexOf<UnsignedInts, T>::value >= 0 };
-    enum { isStdSignedInt   = TL::IndexOf<SignedInts,   T>::value >= 0 };
-    enum { isStdIntegral    = TL::IndexOf<OtherInts,    T>::value >= 0 || isStdUnsignedInt || isStdSignedInt };
-    enum { isStdFloat       = TL::IndexOf<Floats,       T>::value >= 0 };
-    enum { isPointer        = PointerTraits<T>::result };
-    enum { isStdArith       = isStdIntegral || isStdFloat };
-
-    // best parameter type for given type
-    typedef typename Select<isStdArith || isPointer, T, const T&>::Result ParameterType;
-};
-
-// -----------------------------------------------------------------------
-}; // namespace android
-
-#endif /* ANDROID_TRAITS_H */
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
deleted file mode 100644
index 24f30ff..0000000
--- a/services/sensorservice/vec.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_VEC_H
-#define ANDROID_VEC_H
-
-#include <math.h>
-
-#include <stdint.h>
-#include <stddef.h>
-
-#include "traits.h"
-
-// -----------------------------------------------------------------------
-
-#define PURE __attribute__((pure))
-
-namespace android {
-
-// -----------------------------------------------------------------------
-// non-inline helpers
-
-template <typename TYPE, size_t SIZE>
-class vec;
-
-template <typename TYPE, size_t SIZE>
-class vbase;
-
-namespace helpers {
-
-template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
-template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
-
-template < template<typename T, size_t S> class VEC,
-    typename TYPE, size_t SIZE, size_t S>
-vec<TYPE, SIZE>& doAssign(
-        vec<TYPE, SIZE>& lhs, const VEC<TYPE, S>& rhs) {
-    const size_t minSize = min(SIZE, S);
-    const size_t maxSize = max(SIZE, S);
-    for (size_t i=0 ; i<minSize ; i++)
-        lhs[i] = rhs[i];
-    for (size_t i=minSize ; i<maxSize ; i++)
-        lhs[i] = 0;
-    return lhs;
-}
-
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-VLHS<TYPE, SIZE> PURE doAdd(
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    VLHS<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs[i] + rhs[i];
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-VLHS<TYPE, SIZE> PURE doSub(
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    VLHS<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs[i] - rhs[i];
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-VEC<TYPE, SIZE> PURE doMulScalar(
-        const VEC<TYPE, SIZE>& lhs,
-        typename TypeTraits<TYPE>::ParameterType rhs) {
-    VEC<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs[i] * rhs;
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-VEC<TYPE, SIZE> PURE doScalarMul(
-        typename TypeTraits<TYPE>::ParameterType lhs,
-        const VEC<TYPE, SIZE>& rhs) {
-    VEC<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs * rhs[i];
-    return r;
-}
-
-}; // namespace helpers
-
-// -----------------------------------------------------------------------
-// Below we define the mathematical operators for vectors.
-// We use template template arguments so we can generically
-// handle the case where the right-hand-size and left-hand-side are
-// different vector types (but with same value_type and size).
-// This is needed for performance when using ".xy{z}" element access
-// on vec<>. Without this, an extra conversion to vec<> would be needed.
-//
-// example:
-//      vec4_t a;
-//      vec3_t b;
-//      vec3_t c = a.xyz + b;
-//
-//  "a.xyz + b" is a mixed-operation between a vbase<> and a vec<>, requiring
-//  a conversion of vbase<> to vec<>. The template gunk below avoids this,
-// by allowing the addition on these different vector types directly
-//
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-inline VLHS<TYPE, SIZE> PURE operator + (
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    return helpers::doAdd(lhs, rhs);
-}
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-inline VLHS<TYPE, SIZE> PURE operator - (
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    return helpers::doSub(lhs, rhs);
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-inline VEC<TYPE, SIZE> PURE operator * (
-        const VEC<TYPE, SIZE>& lhs,
-        typename TypeTraits<TYPE>::ParameterType rhs) {
-    return helpers::doMulScalar(lhs, rhs);
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-inline VEC<TYPE, SIZE> PURE operator * (
-        typename TypeTraits<TYPE>::ParameterType lhs,
-        const VEC<TYPE, SIZE>& rhs) {
-    return helpers::doScalarMul(lhs, rhs);
-}
-
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-TYPE PURE dot_product(
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    TYPE r(0);
-    for (size_t i=0 ; i<SIZE ; i++)
-        r += lhs[i] * rhs[i];
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class V,
-    typename TYPE,
-    size_t SIZE
->
-TYPE PURE length(const V<TYPE, SIZE>& v) {
-    return sqrt(dot_product(v, v));
-}
-
-template <
-    template<typename T, size_t S> class V,
-    typename TYPE,
-    size_t SIZE
->
-TYPE PURE length_squared(const V<TYPE, SIZE>& v) {
-    return dot_product(v, v);
-}
-
-template <
-    template<typename T, size_t S> class V,
-    typename TYPE,
-    size_t SIZE
->
-V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) {
-    return v * (1/length(v));
-}
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE
->
-VLHS<TYPE, 3> PURE cross_product(
-        const VLHS<TYPE, 3>& u,
-        const VRHS<TYPE, 3>& v) {
-    VLHS<TYPE, 3> r;
-    r.x = u.y*v.z - u.z*v.y;
-    r.y = u.z*v.x - u.x*v.z;
-    r.z = u.x*v.y - u.y*v.x;
-    return r;
-}
-
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE> PURE operator - (const vec<TYPE, SIZE>& lhs) {
-    vec<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = -lhs[i];
-    return r;
-}
-
-// -----------------------------------------------------------------------
-
-// This our basic vector type, it just implements the data storage
-// and accessors.
-
-template <typename TYPE, size_t SIZE>
-struct vbase {
-    TYPE v[SIZE];
-    inline const TYPE& operator[](size_t i) const { return v[i]; }
-    inline       TYPE& operator[](size_t i)       { return v[i]; }
-};
-template<> struct vbase<float, 2> {
-    union {
-        float v[2];
-        struct { float x, y; };
-        struct { float s, t; };
-    };
-    inline const float& operator[](size_t i) const { return v[i]; }
-    inline       float& operator[](size_t i)       { return v[i]; }
-};
-template<> struct vbase<float, 3> {
-    union {
-        float v[3];
-        struct { float x, y, z; };
-        struct { float s, t, r; };
-        vbase<float, 2> xy;
-        vbase<float, 2> st;
-    };
-    inline const float& operator[](size_t i) const { return v[i]; }
-    inline       float& operator[](size_t i)       { return v[i]; }
-};
-template<> struct vbase<float, 4> {
-    union {
-        float v[4];
-        struct { float x, y, z, w; };
-        struct { float s, t, r, q; };
-        vbase<float, 3> xyz;
-        vbase<float, 3> str;
-        vbase<float, 2> xy;
-        vbase<float, 2> st;
-    };
-    inline const float& operator[](size_t i) const { return v[i]; }
-    inline       float& operator[](size_t i)       { return v[i]; }
-};
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t SIZE>
-class vec : public vbase<TYPE, SIZE>
-{
-    typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
-    typedef vbase<TYPE, SIZE> base;
-
-public:
-    // STL-like interface.
-    typedef TYPE value_type;
-    typedef TYPE& reference;
-    typedef TYPE const& const_reference;
-    typedef size_t size_type;
-
-    typedef TYPE* iterator;
-    typedef TYPE const* const_iterator;
-    iterator begin() { return base::v; }
-    iterator end() { return base::v + SIZE; }
-    const_iterator begin() const { return base::v; }
-    const_iterator end() const { return base::v + SIZE; }
-    size_type size() const { return SIZE; }
-
-    // -----------------------------------------------------------------------
-    // default constructors
-
-    vec() { }
-    vec(const vec& rhs)  : base(rhs) { }
-    vec(const base& rhs) : base(rhs) { }
-
-    // -----------------------------------------------------------------------
-    // conversion constructors
-
-    vec(pTYPE rhs) {
-        for (size_t i=0 ; i<SIZE ; i++)
-            base::operator[](i) = rhs;
-    }
-
-    template < template<typename T, size_t S> class VEC, size_t S>
-    explicit vec(const VEC<TYPE, S>& rhs) {
-        helpers::doAssign(*this, rhs);
-    }
-
-    explicit vec(TYPE const* array) {
-        for (size_t i=0 ; i<SIZE ; i++)
-            base::operator[](i) = array[i];
-    }
-
-    // -----------------------------------------------------------------------
-    // Assignment
-
-    vec& operator = (const vec& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    vec& operator = (const base& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    vec& operator = (pTYPE rhs) {
-        for (size_t i=0 ; i<SIZE ; i++)
-            base::operator[](i) = rhs;
-        return *this;
-    }
-
-    template < template<typename T, size_t S> class VEC, size_t S>
-    vec& operator = (const VEC<TYPE, S>& rhs) {
-        return helpers::doAssign(*this, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // operation-assignment
-
-    vec& operator += (const vec& rhs);
-    vec& operator -= (const vec& rhs);
-    vec& operator *= (pTYPE rhs);
-
-    // -----------------------------------------------------------------------
-    // non-member function declaration and definition
-    // NOTE: we declare the non-member function as friend inside the class
-    // so that they are known to the compiler when the class is instantiated.
-    // This helps the compiler doing template argument deduction when the
-    // passed types are not identical. Essentially this helps with
-    // type conversion so that you can multiply a vec<float> by an scalar int
-    // (for instance).
-
-    friend inline vec PURE operator + (const vec& lhs, const vec& rhs) {
-        return helpers::doAdd(lhs, rhs);
-    }
-    friend inline vec PURE operator - (const vec& lhs, const vec& rhs) {
-        return helpers::doSub(lhs, rhs);
-    }
-    friend inline vec PURE operator * (const vec& lhs, pTYPE v) {
-        return helpers::doMulScalar(lhs, v);
-    }
-    friend inline vec PURE operator * (pTYPE v, const vec& rhs) {
-        return helpers::doScalarMul(v, rhs);
-    }
-    friend inline TYPE PURE dot_product(const vec& lhs, const vec& rhs) {
-        return android::dot_product(lhs, rhs);
-    }
-};
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator += (const vec<TYPE, SIZE>& rhs) {
-    vec<TYPE, SIZE>& lhs(*this);
-    for (size_t i=0 ; i<SIZE ; i++)
-        lhs[i] += rhs[i];
-    return lhs;
-}
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator -= (const vec<TYPE, SIZE>& rhs) {
-    vec<TYPE, SIZE>& lhs(*this);
-    for (size_t i=0 ; i<SIZE ; i++)
-        lhs[i] -= rhs[i];
-    return lhs;
-}
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator *= (vec<TYPE, SIZE>::pTYPE rhs) {
-    vec<TYPE, SIZE>& lhs(*this);
-    for (size_t i=0 ; i<SIZE ; i++)
-        lhs[i] *= rhs;
-    return lhs;
-}
-
-// -----------------------------------------------------------------------
-
-typedef vec<float, 2> vec2_t;
-typedef vec<float, 3> vec3_t;
-typedef vec<float, 4> vec4_t;
-
-// -----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /* ANDROID_VEC_H */
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index c23e868..416900f8 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -179,7 +179,7 @@
                     @Override
                     public List<UserInfo> getUsers() {
                         final ArrayList<UserInfo> users = new ArrayList<UserInfo>();
-                        users.add(new UserInfo(USER_ID, "Primary", UserInfo.FLAG_PRIMARY));
+                        users.add(new UserInfo(USER_ID, "Primary", null, UserInfo.FLAG_PRIMARY));
                         users.add(new UserInfo(USER_ID_GUEST, "Guest", 0));
                         return users;
                     }
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 6d81b71..0d9e4f1 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_JAVA_LIBRARIES := core core-junit framework
+LOCAL_STATIC_JAVA_LIBRARIES := junit-runner
 
 LOCAL_MODULE:= android.test.runner
 
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 86689f3..0399b3b 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -545,7 +545,7 @@
      * @hide
      */
     @Override
-    public void updateUserName(int id, String name) {
+    public void setUserName(int id, String name) {
         throw new UnsupportedOperationException();
     }
 
diff --git a/test-runner/src/junit/runner/BaseTestRunner.java b/test-runner/src/junit/runner/BaseTestRunner.java
deleted file mode 100644
index 8cfd7fa..0000000
--- a/test-runner/src/junit/runner/BaseTestRunner.java
+++ /dev/null
@@ -1,342 +0,0 @@
-package junit.runner;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.text.NumberFormat;
-import java.util.Properties;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestListener;
-import junit.framework.TestSuite;
-
-/**
- * Base class for all test runners.
- * This class was born live on stage in Sardinia during XP2000.
- */
-public abstract class BaseTestRunner implements TestListener {
-    public static final String SUITE_METHODNAME= "suite";
-
-    private static Properties fPreferences;
-    static int fgMaxMessageLength= 500;
-    static boolean fgFilterStack= true;
-    boolean fLoading= true;
-
-    /*
-     * Implementation of TestListener
-     */
-    public synchronized void startTest(Test test) {
-        testStarted(test.toString());
-    }
-
-    protected static void setPreferences(Properties preferences) {
-        fPreferences= preferences;
-    }
-
-    protected static Properties getPreferences() {
-        if (fPreferences == null) {
-            fPreferences= new Properties();
-            fPreferences.put("loading", "true");
-            fPreferences.put("filterstack", "true");
-            readPreferences();
-        }
-        return fPreferences;
-    }
-
-    public static void savePreferences() throws IOException {
-        FileOutputStream fos= new FileOutputStream(getPreferencesFile());
-        try {
-            getPreferences().store(fos, "");
-        } finally {
-            fos.close();
-        }
-    }
-
-    // android-changed remove 'static' qualifier for API compatibility
-    public void setPreference(String key, String value) {
-        getPreferences().put(key, value);
-    }
-
-    public synchronized void endTest(Test test) {
-        testEnded(test.toString());
-    }
-
-    public synchronized void addError(final Test test, final Throwable t) {
-        testFailed(TestRunListener.STATUS_ERROR, test, t);
-    }
-
-    public synchronized void addFailure(final Test test, final AssertionFailedError t) {
-        testFailed(TestRunListener.STATUS_FAILURE, test, t);
-    }
-
-    // TestRunListener implementation
-
-    public abstract void testStarted(String testName);
-
-    public abstract void testEnded(String testName);
-
-    public abstract void testFailed(int status, Test test, Throwable t);
-
-    /**
-     * Returns the Test corresponding to the given suite. This is
-     * a template method, subclasses override runFailed(), clearStatus().
-     */
-    public Test getTest(String suiteClassName) {
-        if (suiteClassName.length() <= 0) {
-            clearStatus();
-            return null;
-        }
-        Class testClass= null;
-        try {
-            testClass= loadSuiteClass(suiteClassName);
-        } catch (ClassNotFoundException e) {
-            String clazz= e.getMessage();
-            if (clazz == null)
-                clazz= suiteClassName;
-            runFailed("Class not found \""+clazz+"\"");
-            return null;
-        } catch(Exception e) {
-            runFailed("Error: "+e.toString());
-            return null;
-        }
-        Method suiteMethod= null;
-        try {
-            suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
-        } catch(Exception e) {
-            // try to extract a test suite automatically
-            clearStatus();
-            return new TestSuite(testClass);
-        }
-        if (! Modifier.isStatic(suiteMethod.getModifiers())) {
-            runFailed("Suite() method must be static");
-            return null;
-        }
-        Test test= null;
-        try {
-            test= (Test)suiteMethod.invoke(null, (Object[])new Class[0]); // static method
-            if (test == null)
-                return test;
-        }
-        catch (InvocationTargetException e) {
-            runFailed("Failed to invoke suite():" + e.getTargetException().toString());
-            return null;
-        }
-        catch (IllegalAccessException e) {
-            runFailed("Failed to invoke suite():" + e.toString());
-            return null;
-        }
-
-        clearStatus();
-        return test;
-    }
-
-    /**
-     * Returns the formatted string of the elapsed time.
-     */
-    public String elapsedTimeAsString(long runTime) {
-        return NumberFormat.getInstance().format((double)runTime/1000);
-    }
-
-    /**
-     * Processes the command line arguments and
-     * returns the name of the suite class to run or null
-     */
-    protected String processArguments(String[] args) {
-        String suiteName= null;
-        for (int i= 0; i < args.length; i++) {
-            if (args[i].equals("-noloading")) {
-                setLoading(false);
-            } else if (args[i].equals("-nofilterstack")) {
-                fgFilterStack= false;
-            } else if (args[i].equals("-c")) {
-                if (args.length > i+1)
-                    suiteName= extractClassName(args[i+1]);
-                else
-                    System.out.println("Missing Test class name");
-                i++;
-            } else {
-                suiteName= args[i];
-            }
-        }
-        return suiteName;
-    }
-
-    /**
-     * Sets the loading behaviour of the test runner
-     */
-    public void setLoading(boolean enable) {
-        fLoading= enable;
-    }
-    /**
-     * Extract the class name from a String in VA/Java style
-     */
-    public String extractClassName(String className) {
-        if(className.startsWith("Default package for"))
-            return className.substring(className.lastIndexOf(".")+1);
-        return className;
-    }
-
-    /**
-     * Truncates a String to the maximum length.
-     */
-    public static String truncate(String s) {
-        if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
-            s= s.substring(0, fgMaxMessageLength)+"...";
-        return s;
-    }
-
-    /**
-     * Override to define how to handle a failed loading of
-     * a test suite.
-     */
-    protected abstract void runFailed(String message);
-
-    // BEGIN android-changed - add back getLoader() for API compatibility
-    /**
-     * Returns the loader to be used.
-     * 
-     * @deprecated not present in JUnit4.10
-     */
-    public TestSuiteLoader getLoader() {
-        if (useReloadingTestSuiteLoader())
-            return new ReloadingTestSuiteLoader();
-        return new StandardTestSuiteLoader();
-    }
-    // END android-changed
-
-    /**
-     * Returns the loaded Class for a suite name.
-     */
-    protected Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
-        return Class.forName(suiteClassName);
-    }
-
-    /**
-     * Clears the status message.
-     */
-    protected void clearStatus() { // Belongs in the GUI TestRunner class
-    }
-
-    protected boolean useReloadingTestSuiteLoader() {
-        return getPreference("loading").equals("true") && fLoading;
-    }
-
-    private static File getPreferencesFile() {
-        String home= System.getProperty("user.home");
-        return new File(home, "junit.properties");
-    }
-
-    private static void readPreferences() {
-        InputStream is= null;
-        try {
-            is= new FileInputStream(getPreferencesFile());
-            setPreferences(new Properties(getPreferences()));
-            getPreferences().load(is);
-        } catch (IOException e) {
-            try {
-                if (is != null)
-                    is.close();
-            } catch (IOException e1) {
-            }
-        }
-    }
-
-    public static String getPreference(String key) {
-        return getPreferences().getProperty(key);
-    }
-
-    public static int getPreference(String key, int dflt) {
-        String value= getPreference(key);
-        int intValue= dflt;
-        if (value == null)
-            return intValue;
-        try {
-            intValue= Integer.parseInt(value);
-        } catch (NumberFormatException ne) {
-        }
-        return intValue;
-    }
-
-    /**
-     * Returns a filtered stack trace
-     */
-    public static String getFilteredTrace(Throwable t) {
-        StringWriter stringWriter= new StringWriter();
-        PrintWriter writer= new PrintWriter(stringWriter);
-        t.printStackTrace(writer);
-        StringBuffer buffer= stringWriter.getBuffer();
-        String trace= buffer.toString();
-        return BaseTestRunner.getFilteredTrace(trace);
-    }
-
-    // BEGIN android-changed - add back this method for API compatibility
-    /** @deprecated not present in JUnit4.10 */
-    public static boolean inVAJava() {
-        return false;
-    }
-    // END android-changed
-
-    /**
-     * Filters stack frames from internal JUnit classes
-     */
-    public static String getFilteredTrace(String stack) {
-        if (showStackRaw())
-            return stack;
-
-        StringWriter sw= new StringWriter();
-        PrintWriter pw= new PrintWriter(sw);
-        StringReader sr= new StringReader(stack);
-        // BEGIN android-changed
-        // Use a sensible default buffer size
-        BufferedReader br= new BufferedReader(sr, 1000);
-        // END android-changed
-
-        String line;
-        try {
-            while ((line= br.readLine()) != null) {
-                if (!filterLine(line))
-                    pw.println(line);
-            }
-        } catch (Exception IOException) {
-            return stack; // return the stack unfiltered
-        }
-        return sw.toString();
-    }
-
-    protected static boolean showStackRaw() {
-        return !getPreference("filterstack").equals("true") || fgFilterStack == false;
-    }
-
-    static boolean filterLine(String line) {
-        String[] patterns= new String[] {
-                "junit.framework.TestCase",
-                "junit.framework.TestResult",
-                "junit.framework.TestSuite",
-                "junit.framework.Assert.", // don't filter AssertionFailure
-                "junit.swingui.TestRunner",
-                "junit.awtui.TestRunner",
-                "junit.textui.TestRunner",
-                "java.lang.reflect.Method.invoke("
-        };
-        for (int i= 0; i < patterns.length; i++) {
-            if (line.indexOf(patterns[i]) > 0)
-                return true;
-        }
-        return false;
-    }
-
-    static {
-        fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
-    }
-
-}
diff --git a/test-runner/src/junit/runner/StandardTestSuiteLoader.java b/test-runner/src/junit/runner/StandardTestSuiteLoader.java
deleted file mode 100644
index 381e684..0000000
--- a/test-runner/src/junit/runner/StandardTestSuiteLoader.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-
-/**
- * The standard test suite loader. It can only load the same class once.
- * {@hide} - Not needed for 1.0 SDK
- */
-public class StandardTestSuiteLoader implements TestSuiteLoader {
-    /**
-     * Uses the system class loader to load the test class
-     */
-    public Class load(String suiteClassName) throws ClassNotFoundException {
-        return Class.forName(suiteClassName);
-    }
-    /**
-     * Uses the system class loader to load the test class
-     */
-    public Class reload(Class aClass) throws ClassNotFoundException {
-        return aClass;
-    }
-}
diff --git a/test-runner/src/junit/runner/TestRunListener.java b/test-runner/src/junit/runner/TestRunListener.java
deleted file mode 100644
index 0410f0c..0000000
--- a/test-runner/src/junit/runner/TestRunListener.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-/**
- * A listener interface for observing the
- * execution of a test run. Unlike TestListener,
- * this interface using only primitive objects,
- * making it suitable for remote test execution.
- * {@hide} - Not needed for 1.0 SDK
- */
-public interface TestRunListener {
-    /* test status constants*/
-    public static final int STATUS_ERROR= 1;
-    public static final int STATUS_FAILURE= 2;
-
-    public void testRunStarted(String testSuiteName, int testCount);
-    public void testRunEnded(long elapsedTime);
-    public void testRunStopped(long elapsedTime);
-    public void testStarted(String testName);
-    public void testEnded(String testName);
-    public void testFailed(int status, String testName, String trace);
-}
diff --git a/test-runner/src/junit/runner/TestSuiteLoader.java b/test-runner/src/junit/runner/TestSuiteLoader.java
deleted file mode 100644
index 581ea23..0000000
--- a/test-runner/src/junit/runner/TestSuiteLoader.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package junit.runner;
-
-/**
- * An interface to define how a test suite should be loaded.
- */
-public interface TestSuiteLoader {
-    abstract public Class load(String suiteClassName) throws ClassNotFoundException;
-    abstract public Class reload(Class aClass) throws ClassNotFoundException;
-}
diff --git a/test-runner/src/junit/runner/Version.java b/test-runner/src/junit/runner/Version.java
deleted file mode 100644
index 4a6dc85..0000000
--- a/test-runner/src/junit/runner/Version.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-
-/**
- * This class defines the current version of JUnit
- */
-public class Version {
-    private Version() {
-        // don't instantiate
-    }
-
-    public static String id() {
-        return "4.10";
-    }
-
-    // android-changed
-    /** @hide - not needed for public API */
-    public static void main(String[] args) {
-        System.out.println(id());
-    }
-}
diff --git a/test-runner/src/junit/textui/ResultPrinter.java b/test-runner/src/junit/textui/ResultPrinter.java
deleted file mode 100644
index 4b26558..0000000
--- a/test-runner/src/junit/textui/ResultPrinter.java
+++ /dev/null
@@ -1,142 +0,0 @@
-
-package junit.textui;
-
-import java.io.PrintStream;
-// The following line was removed for compatibility with Android libraries.
-//import java.text.NumberFormat;
-import java.util.Enumeration;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestFailure;
-import junit.framework.TestListener;
-import junit.framework.TestResult;
-import junit.runner.BaseTestRunner;
-
-public class ResultPrinter implements TestListener {
-    PrintStream fWriter;
-    int fColumn= 0;
-
-    public ResultPrinter(PrintStream writer) {
-        fWriter= writer;
-    }
-
-    /* API for use by textui.TestRunner
-     */
-
-    synchronized void print(TestResult result, long runTime) {
-        printHeader(runTime);
-        printErrors(result);
-        printFailures(result);
-        printFooter(result);
-    }
-
-    void printWaitPrompt() {
-        getWriter().println();
-        getWriter().println("<RETURN> to continue");
-    }
-
-    /* Internal methods
-     */
-
-    protected void printHeader(long runTime) {
-        getWriter().println();
-        getWriter().println("Time: "+elapsedTimeAsString(runTime));
-    }
-
-    protected void printErrors(TestResult result) {
-        printDefects(result.errors(), result.errorCount(), "error");
-    }
-
-    protected void printFailures(TestResult result) {
-        printDefects(result.failures(), result.failureCount(), "failure");
-    }
-
-    protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) {
-        if (count == 0) return;
-        if (count == 1)
-            getWriter().println("There was " + count + " " + type + ":");
-        else
-            getWriter().println("There were " + count + " " + type + "s:");
-        for (int i= 1; booBoos.hasMoreElements(); i++) {
-            printDefect(booBoos.nextElement(), i);
-        }
-    }
-
-    public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
-        printDefectHeader(booBoo, count);
-        printDefectTrace(booBoo);
-    }
-
-    protected void printDefectHeader(TestFailure booBoo, int count) {
-        // I feel like making this a println, then adding a line giving the throwable a chance to print something
-        // before we get to the stack trace.
-        getWriter().print(count + ") " + booBoo.failedTest());
-    }
-
-    protected void printDefectTrace(TestFailure booBoo) {
-        getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
-    }
-
-    protected void printFooter(TestResult result) {
-        if (result.wasSuccessful()) {
-            getWriter().println();
-            getWriter().print("OK");
-            getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
-
-        } else {
-            getWriter().println();
-            getWriter().println("FAILURES!!!");
-            getWriter().println("Tests run: "+result.runCount()+
-                    ",  Failures: "+result.failureCount()+
-                    ",  Errors: "+result.errorCount());
-        }
-        getWriter().println();
-    }
-
-
-    /**
-     * Returns the formatted string of the elapsed time.
-     * Duplicated from BaseTestRunner. Fix it.
-     */
-    protected String elapsedTimeAsString(long runTime) {
-        // The following line was altered for compatibility with
-        // Android libraries.
-        return Double.toString((double)runTime/1000);
-    }
-
-    public PrintStream getWriter() {
-        return fWriter;
-    }
-    /**
-     * @see junit.framework.TestListener#addError(Test, Throwable)
-     */
-    public void addError(Test test, Throwable t) {
-        getWriter().print("E");
-    }
-
-    /**
-     * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
-     */
-    public void addFailure(Test test, AssertionFailedError t) {
-        getWriter().print("F");
-    }
-
-    /**
-     * @see junit.framework.TestListener#endTest(Test)
-     */
-    public void endTest(Test test) {
-    }
-
-    /**
-     * @see junit.framework.TestListener#startTest(Test)
-     */
-    public void startTest(Test test) {
-        getWriter().print(".");
-        if (fColumn++ >= 40) {
-            getWriter().println();
-            fColumn= 0;
-        }
-    }
-
-}
diff --git a/test-runner/src/junit/textui/TestRunner.java b/test-runner/src/junit/textui/TestRunner.java
deleted file mode 100644
index e955e0e..0000000
--- a/test-runner/src/junit/textui/TestRunner.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package junit.textui;
-
-
-import java.io.PrintStream;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-import junit.framework.TestSuite;
-import junit.runner.BaseTestRunner;
-import junit.runner.Version;
-
-/**
- * A command line based tool to run tests.
- * <pre>
- * java junit.textui.TestRunner [-wait] TestCaseClass
- * </pre>
- * 
- * <p>TestRunner expects the name of a TestCase class as argument.
- * If this class defines a static <code>suite</code> method it
- * will be invoked and the returned test is run. Otherwise all
- * the methods starting with "test" having no arguments are run.
- * <p>
- * When the wait command line argument is given TestRunner
- * waits until the users types RETURN.
- * <p>
- * TestRunner prints a trace as the tests are executed followed by a
- * summary at the end.
- */
-public class TestRunner extends BaseTestRunner {
-    private ResultPrinter fPrinter;
-
-    public static final int SUCCESS_EXIT= 0;
-    public static final int FAILURE_EXIT= 1;
-    public static final int EXCEPTION_EXIT= 2;
-
-    /**
-     * Constructs a TestRunner.
-     */
-    public TestRunner() {
-        this(System.out);
-    }
-
-    /**
-     * Constructs a TestRunner using the given stream for all the output
-     */
-    public TestRunner(PrintStream writer) {
-        this(new ResultPrinter(writer));
-    }
-
-    /**
-     * Constructs a TestRunner using the given ResultPrinter all the output
-     */
-    public TestRunner(ResultPrinter printer) {
-        fPrinter= printer;
-    }
-
-    /**
-     * Runs a suite extracted from a TestCase subclass.
-     */
-    static public void run(Class<? extends TestCase> testClass) {
-        run(new TestSuite(testClass));
-    }
-
-    /**
-     * Runs a single test and collects its results.
-     * This method can be used to start a test run
-     * from your program.
-     * <pre>
-     * public static void main (String[] args) {
-     *    test.textui.TestRunner.run(suite());
-     * }
-     * </pre>
-     */
-    static public TestResult run(Test test) {
-        TestRunner runner= new TestRunner();
-        return runner.doRun(test);
-    }
-
-    /**
-     * Runs a single test and waits until the user
-     * types RETURN.
-     */
-    static public void runAndWait(Test suite) {
-        TestRunner aTestRunner= new TestRunner();
-        aTestRunner.doRun(suite, true);
-    }
-
-    @Override
-    public void testFailed(int status, Test test, Throwable t) {
-    }
-
-    @Override
-    public void testStarted(String testName) {
-    }
-
-    @Override
-    public void testEnded(String testName) {
-    }
-
-    /**
-     * Creates the TestResult to be used for the test run.
-     */
-    protected TestResult createTestResult() {
-        return new TestResult();
-    }
-
-    public TestResult doRun(Test test) {
-        return doRun(test, false);
-    }
-
-    public TestResult doRun(Test suite, boolean wait) {
-        TestResult result= createTestResult();
-        result.addListener(fPrinter);
-        long startTime= System.currentTimeMillis();
-        suite.run(result);
-        long endTime= System.currentTimeMillis();
-        long runTime= endTime-startTime;
-        fPrinter.print(result, runTime);
-
-        pause(wait);
-        return result;
-    }
-
-    protected void pause(boolean wait) {
-        if (!wait) return;
-        fPrinter.printWaitPrompt();
-        try {
-            System.in.read();
-        }
-        catch(Exception e) {
-        }
-    }
-
-    public static void main(String args[]) {
-        TestRunner aTestRunner= new TestRunner();
-        try {
-            TestResult r= aTestRunner.start(args);
-            if (!r.wasSuccessful())
-                System.exit(FAILURE_EXIT);
-            System.exit(SUCCESS_EXIT);
-        } catch(Exception e) {
-            System.err.println(e.getMessage());
-            System.exit(EXCEPTION_EXIT);
-        }
-    }
-
-    /**
-     * Starts a test run. Analyzes the command line arguments
-     * and runs the given test suite.
-     */
-    public TestResult start(String args[]) throws Exception {
-        String testCase= "";
-        String method= "";
-        boolean wait= false;
-
-        for (int i= 0; i < args.length; i++) {
-            if (args[i].equals("-wait"))
-                wait= true;
-            else if (args[i].equals("-c"))
-                testCase= extractClassName(args[++i]);
-            else if (args[i].equals("-m")) {
-                String arg= args[++i];
-                int lastIndex= arg.lastIndexOf('.');
-                testCase= arg.substring(0, lastIndex);
-                method= arg.substring(lastIndex + 1);
-            } else if (args[i].equals("-v"))
-                System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
-            else
-                testCase= args[i];
-        }
-
-        if (testCase.equals(""))
-            throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
-
-        try {
-            if (!method.equals(""))
-                return runSingleMethod(testCase, method, wait);
-            Test suite= getTest(testCase);
-            return doRun(suite, wait);
-        } catch (Exception e) {
-            throw new Exception("Could not create and run test suite: " + e);
-        }
-    }
-
-    protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
-        Class<? extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class);
-        Test test= TestSuite.createTest(testClass, method);
-        return doRun(test, wait);
-    }
-
-    @Override
-    protected void runFailed(String message) {
-        System.err.println(message);
-        System.exit(FAILURE_EXIT);
-    }
-
-    public void setPrinter(ResultPrinter printer) {
-        fPrinter= printer;
-    }
-
-
-}
diff --git a/tests/BiDiTests/AndroidPrivate.mk b/tests/BiDiTests/Android.mk
similarity index 100%
rename from tests/BiDiTests/AndroidPrivate.mk
rename to tests/BiDiTests/Android.mk
diff --git a/tests/Compatibility/Android.mk b/tests/Compatibility/Android.mk
new file mode 100644
index 0000000..5385413
--- /dev/null
+++ b/tests/Compatibility/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+	$(call all-java-files-under, src)
+
+
+LOCAL_SDK_VERSION := 8
+LOCAL_PACKAGE_NAME := AppCompatibilityTest
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/Compatibility/AndroidManifest.xml b/tests/Compatibility/AndroidManifest.xml
new file mode 100644
index 0000000..103ef4c
--- /dev/null
+++ b/tests/Compatibility/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.compatibilitytest" >
+    <application >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name=".AppCompatibilityRunner"
+        android:targetPackage="com.android.compatibilitytest"
+        android:label="App Compability Test Runner" />
+
+    <uses-sdk android:minSdkVersion="8"></uses-sdk>
+</manifest>
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
new file mode 100644
index 0000000..4d60c83
--- /dev/null
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibilitytest;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.Collection;
+
+/**
+ * Application Compatibility Test that launches an application and detects crashes.
+ */
+public class AppCompatibility extends InstrumentationTestCase {
+
+    private static final String TAG = "AppCompability";
+    private static final String PACKAGE_TO_LAUNCH = "package_to_launch";
+    private static final String APP_LAUNCH_TIMEOUT_MSECS = "app_launch_timeout_ms";
+    private static final String WORKSPACE_LAUNCH_TIMEOUT_MSECS = "workspace_launch_timeout_ms";
+
+    private int mAppLaunchTimeout = 7000;
+    private int mWorkspaceLaunchTimeout = 2000;
+
+    private Context mContext;
+    private ActivityManager mActivityManager;
+    private PackageManager mPackageManager;
+    private AppCompatibilityRunner mRunner;
+    private Bundle mArgs;
+
+    @Override
+    public void setUp() throws Exception{
+        super.setUp();
+        mRunner = (AppCompatibilityRunner) getInstrumentation();
+        assertNotNull("Could not fetch InstrumentationTestRunner.",mRunner);
+
+        mContext = mRunner.getTargetContext();
+        Assert.assertNotNull("Could not get the Context", mContext);
+
+        mActivityManager = (ActivityManager)
+                mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        Assert.assertNotNull("Could not get Activity Manager", mActivityManager);
+
+        mPackageManager = mContext.getPackageManager();
+        Assert.assertNotNull("Missing Package Manager", mPackageManager);
+
+        mArgs = mRunner.getBundle();
+
+        // Parse optional inputs.
+        String appLaunchTimeoutMsecs = mArgs.getString(APP_LAUNCH_TIMEOUT_MSECS);
+        if (appLaunchTimeoutMsecs != null) {
+            mAppLaunchTimeout = Integer.parseInt(appLaunchTimeoutMsecs);
+        }
+        String workspaceLaunchTimeoutMsecs = mArgs.getString(WORKSPACE_LAUNCH_TIMEOUT_MSECS);
+        if (workspaceLaunchTimeoutMsecs != null) {
+            mWorkspaceLaunchTimeout = Integer.parseInt(workspaceLaunchTimeoutMsecs);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Actual test case that launches the package and throws an exception on the first error.
+     * @throws Exception
+     */
+    public void testAppStability() throws Exception {
+        String packageName = mArgs.getString(PACKAGE_TO_LAUNCH);
+        if (packageName != null) {
+            Log.d(TAG, "Launching app " + packageName);
+            Collection<ProcessErrorStateInfo> err = launchActivity(packageName);
+            // Make sure there are no errors when launching the application, otherwise raise an
+            // exception with the first error encountered.
+            assertNull(getFirstError(err), err);
+        } else {
+            Log.d(TAG, "Missing argument, use " + PACKAGE_TO_LAUNCH +
+                    " to specify the package to launch");
+        }
+    }
+
+    /**
+     * Gets the first error in collection and return the long message for it.
+     * @param in {@link Collection} of {@link ProcessErrorStateInfo} to parse.
+     * @return {@link String} the long message of the error.
+     */
+    private String getFirstError(Collection<ProcessErrorStateInfo> in) {
+        if (in == null) {
+            return null;
+        }
+        ProcessErrorStateInfo err = in.iterator().next();
+        if (err != null) {
+            return err.stackTrace;
+        }
+        return null;
+    }
+
+    /**
+     * Launches and activity and queries for errors.
+     * @param packageName {@link String} the package name of the application to launch.
+     * @return  {@link Collection} of {@link ProcessErrorStateInfo} detected during the app launch.
+     */
+    private Collection<ProcessErrorStateInfo> launchActivity(String packageName) {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        Intent intent = mPackageManager.getLaunchIntentForPackage(packageName);
+
+        // We check for any Crash or ANR dialogs that are already up, and we ignore them.  This is
+        // so that we don't report crashes that were caused by prior apps (which those particular
+        // tests should have caught and reported already).  Otherwise, test failures would cascade
+        // from the initial broken app to many/all of the tests following that app's launch.
+        final Collection<ProcessErrorStateInfo> preErr = mActivityManager.getProcessesInErrorState();
+
+        // Launch Activity
+        mContext.startActivity(intent);
+
+        try {
+            Thread.sleep(mAppLaunchTimeout);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        // Send the "home" intent and wait 2 seconds for us to get there
+        mContext.startActivity(homeIntent);
+        try {
+            Thread.sleep(mWorkspaceLaunchTimeout);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        // See if there are any errors.  We wait until down here to give ANRs as much time as
+        // possible to occur.
+        final Collection<ProcessErrorStateInfo> postErr =
+                mActivityManager.getProcessesInErrorState();
+        // Take the difference between the error processes we see now, and the ones that were
+        // present when we started
+        if (preErr != null && postErr != null) {
+            postErr.removeAll(preErr);
+        }
+        return postErr;
+    }
+}
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
new file mode 100644
index 0000000..258937f
--- /dev/null
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibilitytest;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+
+public class AppCompatibilityRunner extends InstrumentationTestRunner {
+
+    private Bundle mArgs;
+
+    @Override
+    public void onCreate(Bundle args) {
+        super.onCreate(args);
+        mArgs = args;
+    }
+
+    public Bundle getBundle() {
+        return mArgs;
+    }
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index d74f5f7..9d621d6 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -19,7 +19,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.webkit.MockGeolocation;
 import android.webkit.WebStorage;
 
 import java.util.HashMap;
@@ -48,7 +47,6 @@
     private static final int EVENT_CLEAR_TOUCH_POINTS = 17;
     private static final int EVENT_CANCEL_TOUCH_POINT = 18;
     private static final int EVENT_SET_TOUCH_MODIFIER = 19;
-    
     private static final int LAYOUT_CLEAR_LIST = 20;
     private static final int LAYOUT_DISPLAY = 21;
     private static final int LAYOUT_DUMP_TEXT = 22;
@@ -72,10 +70,9 @@
     private static final int LAYOUT_WAIT_UNTIL_DONE = 40;
     private static final int LAYOUT_DUMP_DATABASE_CALLBACKS = 41;
     private static final int LAYOUT_SET_CAN_OPEN_WINDOWS = 42;
-    private static final int SET_GEOLOCATION_PERMISSION = 43;
-    private static final int OVERRIDE_PREFERENCE = 44;
-    private static final int LAYOUT_DUMP_CHILD_FRAMES_TEXT = 45;
-    private static final int SET_XSS_AUDITOR_ENABLED = 46;
+    private static final int OVERRIDE_PREFERENCE = 43;
+    private static final int LAYOUT_DUMP_CHILD_FRAMES_TEXT = 44;
+    private static final int SET_XSS_AUDITOR_ENABLED = 45;
     
     CallbackProxy(EventSender eventSender, 
             LayoutTestController layoutTestController) {
@@ -269,11 +266,6 @@
             mLayoutTestController.setCanOpenWindows();
             break;
 
-        case SET_GEOLOCATION_PERMISSION:
-            mLayoutTestController.setGeolocationPermission(
-                    msg.arg1 == 1 ? true : false);
-            break;
-
         case OVERRIDE_PREFERENCE:
             String key = msg.getData().getString("key");
             boolean value = msg.getData().getBoolean("value");
@@ -497,17 +489,23 @@
     public void setMockGeolocationPosition(double latitude,
                                            double longitude,
                                            double accuracy) {
-        MockGeolocation.getInstance().setPosition(latitude,
-                                                  longitude,
-                                                  accuracy);
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setMockGeolocationPosition(latitude,
+                                                         longitude,
+                                                         accuracy);
     }
 
     public void setMockGeolocationError(int code, String message) {
-        MockGeolocation.getInstance().setError(code, message);
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setMockGeolocationError(code, message);
     }
 
     public void setGeolocationPermission(boolean allow) {
-        obtainMessage(SET_GEOLOCATION_PERMISSION, allow ? 1 : 0, 0).sendToTarget();
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setGeolocationPermission(allow);
     }
 
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
index 9be2f1c..c936a6c 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
@@ -72,6 +72,10 @@
     // For XSSAuditor tests
     public void setXSSAuditorEnabled(boolean flag);
 
+    // For Geolocation tests
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy);
+    public void setMockGeolocationError(int code, String message);
+
     // For DeviceOrientation tests
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
             boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index bbfbfc4..42d6457 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -539,24 +539,21 @@
         mCanOpenWindows = true;
     }
 
-    /**
-     * Sets the Geolocation permission state to be used for all future requests.
-     */
+    @Override
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        WebViewClassic.fromWebView(mWebView).setMockGeolocationPosition(latitude, longitude,
+                accuracy);
+    }
+
+    @Override
+    public void setMockGeolocationError(int code, String message) {
+        WebViewClassic.fromWebView(mWebView).setMockGeolocationError(code, message);
+    }
+
     @Override
     public void setGeolocationPermission(boolean allow) {
-        mIsGeolocationPermissionSet = true;
-        mGeolocationPermission = allow;
-
-        if (mPendingGeolocationPermissionCallbacks != null) {
-            Iterator iter = mPendingGeolocationPermissionCallbacks.keySet().iterator();
-            while (iter.hasNext()) {
-                GeolocationPermissions.Callback callback =
-                        (GeolocationPermissions.Callback) iter.next();
-                String origin = (String) mPendingGeolocationPermissionCallbacks.get(callback);
-                callback.invoke(origin, mGeolocationPermission, false);
-            }
-            mPendingGeolocationPermissionCallbacks = null;
-        }
+        Log.v(LOGTAG, "setGeolocationPermission() allow=" + allow);
+        WebViewClassic.fromWebView(mWebView).setMockGeolocationPermission(allow);
     }
 
     @Override
@@ -749,22 +746,11 @@
             callback.updateQuota(currentQuota + 1024 * 1024 * 5);
         }
 
-        /**
-         * Instructs the client to show a prompt to ask the user to set the
-         * Geolocation permission state for the specified origin.
-         */
         @Override
         public void onGeolocationPermissionsShowPrompt(String origin,
                 GeolocationPermissions.Callback callback) {
-            if (mIsGeolocationPermissionSet) {
-                callback.invoke(origin, mGeolocationPermission, false);
-                return;
-            }
-            if (mPendingGeolocationPermissionCallbacks == null) {
-                mPendingGeolocationPermissionCallbacks =
-                        new HashMap<GeolocationPermissions.Callback, String>();
-            }
-            mPendingGeolocationPermissionCallbacks.put(callback, origin);
+            throw new RuntimeException(
+                    "The WebCore mock used by DRT should bypass the usual permissions flow.");
         }
 
         @Override
@@ -849,9 +835,8 @@
         mPageFinished = false;
         mDumpWebKitData = false;
         setDefaultWebSettings(mWebView);
-        mIsGeolocationPermissionSet = false;
-        mPendingGeolocationPermissionCallbacks = null;
         CookieManager.getInstance().removeAllCookie();
+        mWebViewClassic.setUseMockGeolocation();
     }
 
     private boolean canMoveToNextTest() {
@@ -958,8 +943,4 @@
     static final int DRAW_RUNS = 5;
     static final String DRAW_TIME_LOG = Environment.getExternalStorageDirectory() +
         "/android/page_draw_time.txt";
-
-    private boolean mIsGeolocationPermissionSet;
-    private boolean mGeolocationPermission;
-    private Map mPendingGeolocationPermissionCallbacks;
 }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
index d0c59d3..c9c35ce 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
@@ -80,6 +80,17 @@
                 quota);
     }
 
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        Log.i(LOG_TAG, "setMockGeolocationPosition(): " + "latitude=" + latitude +
+                " longitude=" + longitude + " accuracy=" + accuracy);
+        mLayoutTestsExecutor.setMockGeolocationPosition(latitude, longitude, accuracy);
+    }
+
+    public void setMockGeolocationError(int code, String message) {
+        Log.i(LOG_TAG, "setMockGeolocationError(): " + "code=" + code + " message=" + message);
+        mLayoutTestsExecutor.setMockGeolocationError(code, message);
+    }
+
     public void setGeolocationPermission(boolean allow) {
         mLayoutTestsExecutor.setGeolocationPermission(allow);
     }
@@ -95,17 +106,6 @@
                 canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
     }
 
-    public void setMockGeolocationError(int code, String message) {
-        Log.i(LOG_TAG, "setMockGeolocationError(): " + "code=" + code + " message=" + message);
-        MockGeolocation.getInstance().setError(code, message);
-    }
-
-    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
-        Log.i(LOG_TAG, "setMockGeolocationPosition(): " + "latitude=" + latitude +
-                " longitude=" + longitude + " accuracy=" + accuracy);
-        MockGeolocation.getInstance().setPosition(latitude, longitude, accuracy);
-    }
-
     public void setXSSAuditorEnabled(boolean flag) {
         mLayoutTestsExecutor.setXSSAuditorEnabled(flag);
     }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index f958ade..25ac700 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -109,9 +109,6 @@
     private LayoutTestController mLayoutTestController = new LayoutTestController(this);
     private boolean mCanOpenWindows;
     private boolean mDumpDatabaseCallbacks;
-    private boolean mIsGeolocationPermissionSet;
-    private boolean mGeolocationPermission;
-    private Map<GeolocationPermissions.Callback, String> mPendingGeolocationPermissionCallbacks;
 
     private EventSender mEventSender = new EventSender();
 
@@ -255,15 +252,8 @@
         @Override
         public void onGeolocationPermissionsShowPrompt(String origin,
                 GeolocationPermissions.Callback callback) {
-            if (mIsGeolocationPermissionSet) {
-                callback.invoke(origin, mGeolocationPermission, false);
-                return;
-            }
-            if (mPendingGeolocationPermissionCallbacks == null) {
-                mPendingGeolocationPermissionCallbacks =
-                        new HashMap<GeolocationPermissions.Callback, String>();
-            }
-            mPendingGeolocationPermissionCallbacks.put(callback, origin);
+            throw new RuntimeException(
+                    "The WebCore mock used by DRT should bypass the usual permissions flow.");
         }
     };
 
@@ -394,6 +384,7 @@
         webViewSettings.setPageCacheCapacity(0);
 
         // This is asynchronous, but it gets processed by WebCore before it starts loading pages.
+        WebViewClassic.fromWebView(mCurrentWebView).setUseMockGeolocation();
         WebViewClassic.fromWebView(mCurrentWebView).setUseMockDeviceOrientation();
 
         // Must do this after setting the AppCache path.
@@ -573,9 +564,8 @@
     private static final int MSG_DUMP_CHILD_FRAMES_AS_TEXT = 3;
     private static final int MSG_SET_CAN_OPEN_WINDOWS = 4;
     private static final int MSG_DUMP_DATABASE_CALLBACKS = 5;
-    private static final int MSG_SET_GEOLOCATION_PERMISSION = 6;
-    private static final int MSG_OVERRIDE_PREFERENCE = 7;
-    private static final int MSG_SET_XSS_AUDITOR_ENABLED = 8;
+    private static final int MSG_OVERRIDE_PREFERENCE = 6;
+    private static final int MSG_SET_XSS_AUDITOR_ENABLED = 7;
 
     /** String constants for use with layoutTestController.overridePreference() */
     private final String WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED =
@@ -644,22 +634,6 @@
                     mCanOpenWindows = true;
                     break;
 
-                case MSG_SET_GEOLOCATION_PERMISSION:
-                    mIsGeolocationPermissionSet = true;
-                    mGeolocationPermission = msg.arg1 == 1;
-
-                    if (mPendingGeolocationPermissionCallbacks != null) {
-                        Iterator<GeolocationPermissions.Callback> iter =
-                                mPendingGeolocationPermissionCallbacks.keySet().iterator();
-                        while (iter.hasNext()) {
-                            GeolocationPermissions.Callback callback = iter.next();
-                            String origin = mPendingGeolocationPermissionCallbacks.get(callback);
-                            callback.invoke(origin, mGeolocationPermission, false);
-                        }
-                        mPendingGeolocationPermissionCallbacks = null;
-                    }
-                    break;
-
                 case MSG_SET_XSS_AUDITOR_ENABLED:
                     WebViewClassic.fromWebView(mCurrentWebView).getSettings().
                             setXSSAuditorEnabled(msg.arg1 == 1);
@@ -679,8 +653,6 @@
     private void resetLayoutTestController() {
         mCanOpenWindows = false;
         mDumpDatabaseCallbacks = false;
-        mIsGeolocationPermissionSet = false;
-        mPendingGeolocationPermissionCallbacks = null;
     }
 
     public void dumpAsText(boolean enablePixelTest) {
@@ -721,12 +693,19 @@
         mLayoutTestControllerHandler.sendEmptyMessage(MSG_SET_CAN_OPEN_WINDOWS);
     }
 
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        WebViewClassic.fromWebView(mCurrentWebView).setMockGeolocationPosition(latitude, longitude,
+                accuracy);
+    }
+
+    public void setMockGeolocationError(int code, String message) {
+        WebViewClassic.fromWebView(mCurrentWebView).setMockGeolocationError(code, message);
+    }
+
     public void setGeolocationPermission(boolean allow) {
         Log.i(LOG_TAG, mCurrentTestRelativePath + ": setGeolocationPermission(" + allow +
                 ") called");
-        Message msg = mLayoutTestControllerHandler.obtainMessage(MSG_SET_GEOLOCATION_PERMISSION);
-        msg.arg1 = allow ? 1 : 0;
-        msg.sendToTarget();
+        WebViewClassic.fromWebView(mCurrentWebView).setMockGeolocationPermission(allow);
     }
 
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 9e103ac..e7247a3 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -42,6 +42,15 @@
         </activity>
 
         <activity
+                android:name="BigGradientActivity"
+                android:label="_BigGradient">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="DatePickerActivity"
                 android:label="_DatePicker">
             <intent-filter>
@@ -277,15 +286,6 @@
         </activity>
 
         <activity
-                android:name="ViewLayersActivity6"
-                android:label="_ViewLayers6">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-        <activity
                 android:name="AlphaLayersActivity"
                 android:label="_αLayers">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
index 653f3a8..36cf8c9 100644
--- a/tests/HwAccelerationTest/res/layout/view_layers_5.xml
+++ b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
@@ -26,16 +26,28 @@
         android:layout_weight="1">
 
         <Button
-            android:onClick="setLayerEnabled"
+            android:onClick="enableLayer"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Enable layer" />
 
         <Button
-            android:onClick="setLayerDisabled"
+            android:onClick="disableLayer"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Disable layer" />
+
+        <Button
+            android:onClick="shrinkLayer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Shrink layer" />
+
+        <Button
+            android:onClick="growLayer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Grow layer" />
         
     </LinearLayout>
 
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_6.xml b/tests/HwAccelerationTest/res/layout/view_layers_6.xml
deleted file mode 100644
index 36cf8c9..0000000
--- a/tests/HwAccelerationTest/res/layout/view_layers_6.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="1">
-
-        <Button
-            android:onClick="enableLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Enable layer" />
-
-        <Button
-            android:onClick="disableLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Disable layer" />
-
-        <Button
-            android:onClick="shrinkLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Shrink layer" />
-
-        <Button
-            android:onClick="growLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Grow layer" />
-        
-    </LinearLayout>
-
-    <ListView
-        android:id="@+id/list1"
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="1" />
-
-</LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java
new file mode 100644
index 0000000..4d28f51
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.view.View;
+
+public class BigGradientActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(new BigGradientView(this));
+    }
+
+    private class BigGradientView extends View {
+        public BigGradientView(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            Paint p = new Paint();
+            p.setShader(new LinearGradient(0.0f, 0.0f, 0.0f, getHeight(), 0xff000000,
+                    0xff333333, Shader.TileMode.CLAMP));
+
+            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), p);
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index 0e75b80..733e44f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -22,7 +22,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.opengl.GLUtils;
 import android.os.Bundle;
@@ -278,7 +277,7 @@
             return texture;
         }
         
-        private int buildProgram(String vertex, String fragment) {
+        private static int buildProgram(String vertex, String fragment) {
             int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
             if (vertexShader == 0) return 0;
 
@@ -309,7 +308,7 @@
             return program;
         }
         
-        private int buildShader(String source, int type) {
+        private static int buildShader(String source, int type) {
             int shader = glCreateShader(type);
 
             glShaderSource(shader, source);
@@ -337,7 +336,7 @@
             }
         }
 
-        private void checkGlError() {
+        private static void checkGlError() {
             int error = glGetError();
             if (error != GL_NO_ERROR) {
                 Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
@@ -420,7 +419,7 @@
             return null;
         }
         
-        private int[] getConfig() {
+        private static int[] getConfig() {
             return new int[] {
                     EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                     EGL10.EGL_RED_SIZE, 8,
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 95a5b0d..2664977 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -32,30 +32,40 @@
 
 @SuppressWarnings({"UnusedDeclaration"})
 public class ViewLayersActivity5 extends Activity {
+    private final Paint mPaint = new Paint();
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         
         setContentView(R.layout.view_layers_5);
 
+        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+
         setupList(R.id.list1);
     }
 
-    public void setLayerDisabled(View v) {
-        ((ViewGroup) findViewById(R.id.list1).getParent()).setChildrenLayersEnabled(false);
+    public void enableLayer(View v) {
+        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
+    }
+
+    public void disableLayer(View v) {
+        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
     }
     
-    public void setLayerEnabled(View v) {
-        ((ViewGroup) findViewById(R.id.list1).getParent()).setChildrenLayersEnabled(true);
+    public void growLayer(View v) {
+        findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+        findViewById(R.id.list1).requestLayout();
+    }
+
+    public void shrinkLayer(View v) {
+        findViewById(R.id.list1).getLayoutParams().height = 300;
+        findViewById(R.id.list1).requestLayout();
     }
     
     private void setupList(int listId) {
-        final Paint p = new Paint();
-        p.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
-
         final ListView list = (ListView) findViewById(listId);
         list.setAdapter(new SimpleListAdapter(this));
-        list.setLayerType(View.LAYER_TYPE_HARDWARE, p);
     }
 
     private static class SimpleListAdapter extends ArrayAdapter<String> {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity6.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity6.java
deleted file mode 100644
index 2edfec7..0000000
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity6.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.hwui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-
-@SuppressWarnings({"UnusedDeclaration"})
-public class ViewLayersActivity6 extends Activity {
-    private final Paint mPaint = new Paint();
-    
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        
-        setContentView(R.layout.view_layers_6);
-
-        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
-
-        setupList(R.id.list1);
-    }
-
-    public void enableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
-    }
-    
-    public void disableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
-    }
-    
-    public void growLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
-        findViewById(R.id.list1).requestLayout();
-    }
-    
-    public void shrinkLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = 300;        
-        findViewById(R.id.list1).requestLayout();
-    }
-    
-    private void setupList(int listId) {
-        final ListView list = (ListView) findViewById(listId);
-        list.setAdapter(new SimpleListAdapter(this));
-    }
-
-    private static class SimpleListAdapter extends ArrayAdapter<String> {
-        public SimpleListAdapter(Context context) {
-            super(context, android.R.layout.simple_list_item_1, DATA_LIST);
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            TextView v = (TextView) super.getView(position, convertView, parent);
-            final Resources r = getContext().getResources();
-            final DisplayMetrics metrics = r.getDisplayMetrics();
-            v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
-            v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
-                    null, null, null);
-            return v;
-        }
-    }
-
-    private static final String[] DATA_LIST = {
-            "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
-            "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
-            "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
-            "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
-            "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
-            "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
-            "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
-            "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
-            "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
-            "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
-            "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
-            "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
-            "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
-            "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
-            "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
-            "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
-            "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
-            "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
-            "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
-            "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
-            "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
-            "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
-            "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
-            "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
-            "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
-            "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
-            "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
-            "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
-            "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
-            "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
-            "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
-            "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
-            "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
-            "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
-            "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
-            "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
-            "Ukraine", "United Arab Emirates", "United Kingdom",
-            "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
-            "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
-            "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
-    };
-}
diff --git a/tests/RenderScriptTests/Balls/Android.mk b/tests/RenderScriptTests/Balls/Android.mk
index b109584..77281ce 100644
--- a/tests/RenderScriptTests/Balls/Android.mk
+++ b/tests/RenderScriptTests/Balls/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ComputePerf/Android.mk b/tests/RenderScriptTests/ComputePerf/Android.mk
index 1d67d29..6ed5884 100644
--- a/tests/RenderScriptTests/ComputePerf/Android.mk
+++ b/tests/RenderScriptTests/ComputePerf/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
                    $(call all-renderscript-files-under, src)
diff --git a/tests/RenderScriptTests/FBOTest/Android.mk b/tests/RenderScriptTests/FBOTest/Android.mk
index 1df7b26..434d592 100644
--- a/tests/RenderScriptTests/FBOTest/Android.mk
+++ b/tests/RenderScriptTests/FBOTest/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/Fountain/Android.mk b/tests/RenderScriptTests/Fountain/Android.mk
index 2049ecf..4a6560b 100644
--- a/tests/RenderScriptTests/Fountain/Android.mk
+++ b/tests/RenderScriptTests/Fountain/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/FountainFbo/Android.mk b/tests/RenderScriptTests/FountainFbo/Android.mk
index 55a4fd8..4535eb1 100644
--- a/tests/RenderScriptTests/FountainFbo/Android.mk
+++ b/tests/RenderScriptTests/FountainFbo/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/Fountain_v11/Android.mk b/tests/RenderScriptTests/Fountain_v11/Android.mk
index e51115c..fe7f9e7 100644
--- a/tests/RenderScriptTests/Fountain_v11/Android.mk
+++ b/tests/RenderScriptTests/Fountain_v11/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
diff --git a/tests/RenderScriptTests/HelloWorld/Android.mk b/tests/RenderScriptTests/HelloWorld/Android.mk
index 2af1cdb..54824f4 100644
--- a/tests/RenderScriptTests/HelloWorld/Android.mk
+++ b/tests/RenderScriptTests/HelloWorld/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
index 08a010d..bd56d62 100644
--- a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
+++ b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
@@ -50,8 +50,12 @@
                         android:textSize="8pt"
                         android:text="@string/saturation"/>
             </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/inSaturationText"
+                android:id="@+id/slider1Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
@@ -59,13 +63,13 @@
                 android:layout_marginTop="15sp"
                 android:text="@string/saturation"/>
              <SeekBar
-                android:id="@+id/inSaturation"
+                android:id="@+id/slider1"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/inGammaText"
+                android:id="@+id/slider2Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
@@ -73,13 +77,13 @@
                 android:layout_marginTop="15sp"
                 android:text="@string/gamma"/>
             <SeekBar
-                android:id="@+id/inGamma"
+                android:id="@+id/slider2"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/outWhiteText"
+                android:id="@+id/slider3Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginLeft="10sp"
@@ -87,13 +91,13 @@
                 android:textSize="8pt"
                 android:text="@string/out_white"/>
             <SeekBar
-                android:id="@+id/outWhite"
+                android:id="@+id/slider3"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/inWhiteText"
+                android:id="@+id/slider4Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
@@ -101,49 +105,21 @@
                 android:layout_marginTop="15sp"
                 android:text="@string/in_white"/>
             <SeekBar
-                android:id="@+id/inWhite"
+                android:id="@+id/slider4"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/outBlackText"
+                android:id="@+id/slider5Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
                 android:layout_marginLeft="10sp"
                 android:layout_marginTop="15sp"
-                android:text="@string/out_black"/>
+                android:text="@string/in_white"/>
             <SeekBar
-                android:id="@+id/outBlack"
-                android:layout_marginLeft="10sp"
-                android:layout_marginRight="10sp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
-            <TextView
-                android:id="@+id/inBlackText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textSize="8pt"
-                android:layout_marginLeft="10sp"
-                android:layout_marginTop="15sp"
-                android:text="@string/in_black"/>
-            <SeekBar
-                android:id="@+id/inBlack"
-                android:layout_marginLeft="10sp"
-                android:layout_marginRight="10sp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
-            <TextView
-                android:id="@+id/blurText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textSize="8pt"
-                 android:layout_marginLeft="10sp"
-                android:layout_marginTop="15sp"
-                android:text="@string/blur_description"/>
-            <SeekBar
-                android:id="@+id/radius"
+                android:id="@+id/slider5"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..697bbb1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private ScriptC_vertical_blur mScriptVBlur;
+    private ScriptC_horizontal_blur mScriptHBlur;
+    private int mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        float fRadius = progress / 100.0f;
+        fRadius *= (float)(MAX_RADIUS);
+        mRadius = (int)fRadius;
+        mScript.set_radius(mRadius);
+    }
+    public void onBar2Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        mScriptVBlur.invoke_setSaturation(mSaturation);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur);
+        mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur);
+
+        mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+        mScript.set_width(width);
+        mScript.set_height(height);
+        mScript.set_radius(mRadius);
+
+        mScriptVBlur.invoke_setSaturation(mSaturation);
+
+        mScript.bind_InPixel(mInPixelsAllocation);
+        mScript.bind_OutPixel(mOutPixelsAllocation);
+        mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
+        mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
+
+        mScript.set_vBlurScript(mScriptVBlur);
+        mScript.set_hBlurScript(mScriptHBlur);
+    }
+
+    public void runTest() {
+        mScript.invoke_filter();
+    }
+
+    public void setupBenchmark() {
+        mScript.set_radius(MAX_RADIUS);
+    }
+
+    public void exitBenchmark() {
+        mScript.set_radius(mRadius);
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..cd54c2e
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWidth(width);
+        mScript.set_gHeight(height);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..3db210a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 7368260..3a9838b 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,124 +29,65 @@
 import android.renderscript.Script;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.SeekBar;
+import android.widget.Spinner;
 import android.widget.TextView;
 import android.view.View;
 import android.util.Log;
 import java.lang.Math;
 
 public class ImageProcessingActivity extends Activity
-                                       implements SurfaceHolder.Callback,
-                                       SeekBar.OnSeekBarChangeListener {
+                                       implements SeekBar.OnSeekBarChangeListener {
     private final String TAG = "Img";
-    private Bitmap mBitmapIn;
-    private Bitmap mBitmapOut;
-    private ScriptC_threshold mScript;
-    private ScriptC_vertical_blur mScriptVBlur;
-    private ScriptC_horizontal_blur mScriptHBlur;
-    private int mRadius = 0;
-    private SeekBar mRadiusSeekBar;
+    Bitmap mBitmapIn;
+    Bitmap mBitmapOut;
+    String mTestNames[];
 
-    private float mInBlack = 0.0f;
-    private SeekBar mInBlackSeekBar;
-    private float mOutBlack = 0.0f;
-    private SeekBar mOutBlackSeekBar;
-    private float mInWhite = 255.0f;
-    private SeekBar mInWhiteSeekBar;
-    private float mOutWhite = 255.0f;
-    private SeekBar mOutWhiteSeekBar;
-    private float mGamma = 1.0f;
-    private SeekBar mGammaSeekBar;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
 
     private float mSaturation = 1.0f;
-    private SeekBar mSaturationSeekBar;
 
     private TextView mBenchmarkResult;
-
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private RenderScript mRS;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Type mPixelType;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Allocation mInPixelsAllocation;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Allocation mOutPixelsAllocation;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Allocation mScratchPixelsAllocation1;
-    private Allocation mScratchPixelsAllocation2;
+    private Spinner mTestSpinner;
 
     private SurfaceView mSurfaceView;
     private ImageView mDisplayView;
 
-    private boolean mIsProcessing;
+    private boolean mDoingBenchmark;
 
-    class FilterCallback extends RenderScript.RSMessageHandler {
-        private Runnable mAction = new Runnable() {
-            public void run() {
+    private TestBase mTest;
 
-                synchronized (mDisplayView) {
-                    mIsProcessing = false;
-                }
-
-                mOutPixelsAllocation.copyTo(mBitmapOut);
-                mDisplayView.invalidate();
-            }
-        };
-
-        @Override
-        public void run() {
-            mSurfaceView.removeCallbacks(mAction);
-            mSurfaceView.post(mAction);
-        }
-    }
-
-    int in[];
-    int interm[];
-    int out[];
-    int MAX_RADIUS = 25;
-    // Store our coefficients here
-    float gaussian[];
 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         if (fromUser) {
 
-            if (seekBar == mRadiusSeekBar) {
-                float fRadius = progress / 100.0f;
-                fRadius *= (float)(MAX_RADIUS);
-                mRadius = (int)fRadius;
-
-                mScript.set_radius(mRadius);
-            } else if (seekBar == mInBlackSeekBar) {
-                mInBlack = (float)progress;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mOutBlackSeekBar) {
-                mOutBlack = (float)progress;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mInWhiteSeekBar) {
-                mInWhite = (float)progress + 127.0f;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mOutWhiteSeekBar) {
-                mOutWhite = (float)progress + 127.0f;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mGammaSeekBar) {
-                mGamma = (float)progress/100.0f;
-                mGamma = Math.max(mGamma, 0.1f);
-                mGamma = 1.0f / mGamma;
-                mScriptVBlur.invoke_setGamma(mGamma);
-            } else if (seekBar == mSaturationSeekBar) {
-                mSaturation = (float)progress / 50.0f;
-                mScriptVBlur.invoke_setSaturation(mSaturation);
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
             }
 
-            synchronized (mDisplayView) {
-                if (mIsProcessing) {
-                    return;
-                }
-                mIsProcessing = true;
-            }
-
-            mScript.invoke_filter();
+            mTest.runTest();
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
         }
     }
 
@@ -156,6 +97,87 @@
     public void onStopTrackingTouch(SeekBar seekBar) {
     }
 
+    void setupBars() {
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(int testID) {
+        switch(testID) {
+        case 0:
+            mTest = new LevelsV4(false, false);
+            break;
+        case 1:
+            mTest = new LevelsV4(false, true);
+            break;
+        case 2:
+            mTest = new LevelsV4(true, false);
+            break;
+        case 3:
+            mTest = new LevelsV4(true, true);
+            break;
+        case 4:
+            mTest = new Blur25();
+            break;
+        case 5:
+            mTest = new Greyscale();
+            break;
+        case 6:
+            mTest = new Grain();
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn);
+        setupBars();
+
+        mTest.runTest();
+        mTest.updateBitmap(mBitmapOut);
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[7];
+        mTestNames[0] = "Levels Vec3 Relaxed";
+        mTestNames[1] = "Levels Vec4 Relaxed";
+        mTestNames[2] = "Levels Vec3 Full";
+        mTestNames[3] = "Levels Vec4 Full";
+        mTestNames[4] = "Blur radius 25";
+        mTestNames[5] = "Greyscale";
+        mTestNames[6] = "Grain";
+        mTestSpinner.setAdapter(new ArrayAdapter<String>(
+            this, R.layout.spinner_layout, mTestNames));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(pos);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -165,94 +187,38 @@
         mBitmapOut = loadBitmap(R.drawable.city);
 
         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
-        mSurfaceView.getHolder().addCallback(this);
 
         mDisplayView = (ImageView) findViewById(R.id.display);
         mDisplayView.setImageBitmap(mBitmapOut);
 
-        mRadiusSeekBar = (SeekBar) findViewById(R.id.radius);
-        mRadiusSeekBar.setOnSeekBarChangeListener(this);
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
 
-        mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
-        mInBlackSeekBar.setOnSeekBarChangeListener(this);
-        mInBlackSeekBar.setMax(128);
-        mInBlackSeekBar.setProgress(0);
-        mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
-        mOutBlackSeekBar.setOnSeekBarChangeListener(this);
-        mOutBlackSeekBar.setMax(128);
-        mOutBlackSeekBar.setProgress(0);
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
 
-        mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
-        mInWhiteSeekBar.setOnSeekBarChangeListener(this);
-        mInWhiteSeekBar.setMax(128);
-        mInWhiteSeekBar.setProgress(128);
-        mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
-        mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
-        mOutWhiteSeekBar.setMax(128);
-        mOutWhiteSeekBar.setProgress(128);
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
 
-        mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
-        mGammaSeekBar.setOnSeekBarChangeListener(this);
-        mGammaSeekBar.setMax(150);
-        mGammaSeekBar.setProgress(100);
-
-        mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
-        mSaturationSeekBar.setOnSeekBarChangeListener(this);
-        mSaturationSeekBar.setProgress(50);
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
 
         mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
         mBenchmarkResult.setText("Result: not run");
+
+        setupTests();
+        changeTest(0);
     }
 
-    public void surfaceCreated(SurfaceHolder holder) {
-        createScript();
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
-    }
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-    }
-
-    public void surfaceDestroyed(SurfaceHolder holder) {
-    }
-
-    private void createScript() {
-        mRS = RenderScript.create(this);
-        mRS.setMessageHandler(new FilterCallback());
-
-        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
-                                                          Allocation.MipmapControl.MIPMAP_NONE,
-                                                          Allocation.USAGE_SCRIPT);
-        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
-                                                           Allocation.MipmapControl.MIPMAP_NONE,
-                                                           Allocation.USAGE_SCRIPT);
-
-        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
-        tb.setX(mBitmapIn.getWidth());
-        tb.setY(mBitmapIn.getHeight());
-        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
-        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
-
-        mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur);
-        mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur);
-
-        mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold);
-        mScript.set_width(mBitmapIn.getWidth());
-        mScript.set_height(mBitmapIn.getHeight());
-        mScript.set_radius(mRadius);
-
-        mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-        mScriptVBlur.invoke_setGamma(mGamma);
-        mScriptVBlur.invoke_setSaturation(mSaturation);
-
-        mScript.bind_InPixel(mInPixelsAllocation);
-        mScript.bind_OutPixel(mOutPixelsAllocation);
-        mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
-        mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
-
-        mScript.set_vBlurScript(mScriptVBlur);
-        mScript.set_hBlurScript(mScriptHBlur);
-    }
 
     private Bitmap loadBitmap(int resource) {
         final BitmapFactory.Options options = new BitmapFactory.Options();
@@ -278,26 +244,29 @@
 
     // For benchmark test
     public long getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 2000;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+
         Log.v(TAG, "Benchmarking");
-        int oldRadius = mRadius;
-        mRadius = MAX_RADIUS;
-        mScript.set_radius(mRadius);
-
-        mScript.invoke_filter();
-        mRS.finish();
-
-        long t = java.lang.System.currentTimeMillis();
-
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
-
+        t = java.lang.System.currentTimeMillis();
+        mTest.runTest();
+        mTest.finish();
         t = java.lang.System.currentTimeMillis() - t;
-        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
-        mRadius = oldRadius;
-        mScript.set_radius(mRadius);
 
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
         return t;
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..9eb5647
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Matrix3f;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..3a6241d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mOutPixelsAllocation;
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity act, Bitmap b) {
+        mRS = RenderScript.create(act);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                           Allocation.MipmapControl.MIPMAP_NONE,
+                                                           Allocation.USAGE_SCRIPT);
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+        android.util.Log.e("img", "implement createTest");
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
new file mode 100644
index 0000000..97ae4fb
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+void genRand(uchar *out) {
+    *out = (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWidth;
+int32_t gHeight;
+
+rs_allocation gBlendSource;
+void blend9(uchar *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = min(x+1, (uint32_t)gWidth);
+    uint32_t x2 = max(x-1, (uint32_t)0);
+    uint32_t y1 = min(y+1, (uint32_t)gHeight);
+    uint32_t y2 = max(y-1, (uint32_t)0);
+
+    uint p00 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
+    uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
+    uint p02 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
+    uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
+    uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
+    uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
+    uint p20 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
+    uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
+    uint p22 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    *out = (uchar)(p20 >> 10);
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(*in);
+    float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    *out = p;
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs
new file mode 100644
index 0000000..c420cac
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+void root(const uchar4 *v_in, uchar4 *v_out) {
+    float4 f4 = rsUnpackColor8888(*v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    *v_out = rsPackColorTo8888(mono);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..7c5d930
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float3 pixel = convert_float4(in[0]).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out->xyz = convert_uchar3(pixel);
+    out->w = 0xff;
+}
+
+void root4(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(in[0]);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out->xyzw = convert_uchar4(pixel);
+}
+
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
index 8610627..da6a291 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-using namespace android;
+#include "levels.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
similarity index 69%
rename from cmds/sensorservice/main_sensorservice.cpp
rename to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
index 8610627..b115445 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "levels.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
index d93238c..77cd5be 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -88,6 +88,6 @@
 
     fs.ain = rsGetAllocation(ScratchPixel2);
     rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
-    rsSendToClientBlocking(CMD_FINISHED);
+    //rsSendToClientBlocking(CMD_FINISHED);
 }
 
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
index a6da192..60fd71b 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
@@ -3,29 +3,9 @@
 
 #include "ip.rsh"
 
-static float inBlack;
-static float outBlack;
-static float inWhite;
-static float outWhite;
-static float3 gamma;
 static float saturation;
-
-static float inWMinInB;
-static float outWMinOutB;
-static float overInWMinInB;
 static rs_matrix3x3 colorMat;
 
-void setLevels(float iBlk, float oBlk, float iWht, float oWht) {
-    inBlack = iBlk;
-    outBlack = oBlk;
-    inWhite = iWht;
-    outWhite = oWht;
-
-    inWMinInB = inWhite - inBlack;
-    outWMinOutB = outWhite - outBlack;
-    overInWMinInB = 1.f / inWMinInB;
-}
-
 void setSaturation(float sat) {
     saturation = sat;
 
@@ -52,10 +32,6 @@
     rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation);
 }
 
-void setGamma(float g) {
-    gamma = (float3)g;
-}
-
 void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
     const FilterStruct *fs = (const FilterStruct *)usrData;
     float3 blurredPixel = 0;
@@ -76,12 +52,8 @@
     }
 
     float3 temp = rsMatrixMultiply(&colorMat, blurredPixel);
-    temp = (clamp(temp, 0.f, 255.f) - inBlack) * overInWMinInB;
-    if (gamma.x != 1.0f)
-        temp = pow(temp, (float3)gamma);
-    temp = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f);
-
+    temp = clamp(temp, 0.f, 255.f);
     out->xyz = convert_uchar3(temp);
-    //output->w = input->w;
+    out->w = 0xff;
 }
 
diff --git a/tests/RenderScriptTests/LivePreview/Android.mk b/tests/RenderScriptTests/LivePreview/Android.mk
new file mode 100644
index 0000000..1b45573
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := PreviewRS
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/LivePreview/AndroidManifest.xml b/tests/RenderScriptTests/LivePreview/AndroidManifest.xml
new file mode 100644
index 0000000..1b91464
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2012 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.livepreview">
+    <uses-sdk android:minSdkVersion="14" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <application android:label="Preview FS"
+                 android:hardwareAccelerated="true">
+
+        <activity android:name="CameraPreviewActivity"
+                  android:label="Preview FS"
+                  android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/LivePreview/res/drawable-nodpi/city.png b/tests/RenderScriptTests/LivePreview/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..856eeff
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/drawable-nodpi/city.png
Binary files differ
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/cf_format_list_item.xml b/tests/RenderScriptTests/LivePreview/res/layout/cf_format_list_item.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/cf_format_list_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/cf_main.xml b/tests/RenderScriptTests/LivePreview/res/layout/cf_main.xml
new file mode 100644
index 0000000..c7dcca5
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/cf_main.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" >
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="3" >
+
+            <TextureView
+                android:id="@+id/preview_view"
+                android:layout_height="0dp"
+                android:layout_width="fill_parent"
+                android:layout_weight="3" />
+            <TextView
+                android:id="@+id/preview_label"
+                android:layout_height="wrap_content"
+                android:layout_width="fill_parent"
+                android:text="@string/cf_preview_label"
+                android:padding="2dp"
+                android:textSize="16sp"
+                android:gravity="center" />
+
+        </LinearLayout>
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="3" >
+
+            <ImageView
+                android:id="@+id/format_view"
+                android:layout_height="0dp"
+                android:layout_width="fill_parent"
+                android:layout_weight="3" />
+            <TextView
+                android:id="@+id/format_label"
+                android:layout_height="wrap_content"
+                android:layout_width="fill_parent"
+                android:text="@string/cf_format_label"
+                android:padding="2dp"
+                android:textSize="16sp"
+                android:gravity="center" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="2" >
+
+            <Spinner
+                android:id="@+id/cameras_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/resolution_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/format_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/main.xml b/tests/RenderScriptTests/LivePreview/res/layout/main.xml
new file mode 100644
index 0000000..a6a075c
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/main.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/rs.xml b/tests/RenderScriptTests/LivePreview/res/layout/rs.xml
new file mode 100644
index 0000000..6fde1b9
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/rs.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <TextureView
+                android:id="@+id/display"
+                android:layout_width="800sp"
+                android:layout_height="423sp" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/LivePreview/res/values/strings.xml b/tests/RenderScriptTests/LivePreview/res/values/strings.xml
new file mode 100644
index 0000000..d651bfb
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+
+    <string name="app_name">CTS Verifier</string>
+    <string name="welcome_text">Welcome to the CTS Verifier!</string>
+    <string name="version_text">%1$s</string>
+    <string name="continue_button_text">Continue</string>
+
+    <string name="cf_preview_label">Normal preview</string>
+    <string name="cf_format_label">Processed callback data</string>
+    <string name="camera_format">Camera Formats</string>
+
+
+</resources>
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
new file mode 100644
index 0000000..f21331f
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.rs.livepreview;
+
+//import com.android.cts.verifier.PassFailButtons;
+//import com.android.cts.verifier.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.TextureView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.Spinner;
+
+import java.io.IOException;
+import java.lang.InterruptedException;
+import java.lang.Math;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeSet;
+
+import android.renderscript.*;
+
+/**
+ * Tests for manual verification of the CDD-required camera output formats
+ * for preview callbacks
+ */
+public class CameraPreviewActivity extends Activity
+        implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
+
+    private static final String TAG = "CameraFormats";
+
+    private TextureView mPreviewView;
+    private SurfaceTexture mPreviewTexture;
+    private int mPreviewTexWidth;
+    private int mPreviewTexHeight;
+
+    private ImageView mFormatView;
+
+    private Spinner mCameraSpinner;
+    private Spinner mResolutionSpinner;
+
+    private int mCurrentCameraId = -1;
+    private Camera mCamera;
+
+    private List<Camera.Size> mPreviewSizes;
+    private Camera.Size mNextPreviewSize;
+    private Camera.Size mPreviewSize;
+
+    private Bitmap mCallbackBitmap;
+
+    private static final int STATE_OFF = 0;
+    private static final int STATE_PREVIEW = 1;
+    private static final int STATE_NO_CALLBACKS = 2;
+    private int mState = STATE_OFF;
+    private boolean mProcessInProgress = false;
+    private boolean mProcessingFirstFrame = false;
+
+
+    private RenderScript mRS;
+    private RsYuv mFilterYuv;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.cf_main);
+
+        mPreviewView = (TextureView) findViewById(R.id.preview_view);
+        mFormatView = (ImageView) findViewById(R.id.format_view);
+
+        mPreviewView.setSurfaceTextureListener(this);
+
+        int numCameras = Camera.getNumberOfCameras();
+        String[] cameraNames = new String[numCameras];
+        for (int i = 0; i < numCameras; i++) {
+            cameraNames[i] = "Camera " + i;
+        }
+        mCameraSpinner = (Spinner) findViewById(R.id.cameras_selection);
+        mCameraSpinner.setAdapter(
+            new ArrayAdapter<String>(
+                this, R.layout.cf_format_list_item, cameraNames));
+        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
+
+        mResolutionSpinner = (Spinner) findViewById(R.id.resolution_selection);
+        mResolutionSpinner.setOnItemSelectedListener(mResolutionSelectedListener);
+
+
+        mRS = RenderScript.create(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        setUpCamera(mCameraSpinner.getSelectedItemPosition());
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        shutdownCamera();
+    }
+
+    public void onSurfaceTextureAvailable(SurfaceTexture surface,
+            int width, int height) {
+        mPreviewTexture = surface;
+        mPreviewTexWidth = width;
+        mPreviewTexHeight = height;
+        if (mCamera != null) {
+            startPreview();
+        }
+    }
+
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        // Ignored, Camera does all the work for us
+    }
+
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        return true;
+    }
+
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        // Invoked every time there's a new Camera preview frame
+    }
+
+    private AdapterView.OnItemSelectedListener mCameraSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent,
+                        View view, int pos, long id) {
+                    if (mCurrentCameraId != pos) {
+                        setUpCamera(pos);
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+
+            };
+
+    private AdapterView.OnItemSelectedListener mResolutionSelectedListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent,
+                        View view, int position, long id) {
+                    if (mPreviewSizes.get(position) != mPreviewSize) {
+                        mNextPreviewSize = mPreviewSizes.get(position);
+                        startPreview();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+
+            };
+
+
+    private void setUpCamera(int id) {
+        shutdownCamera();
+
+        mCurrentCameraId = id;
+        mCamera = Camera.open(id);
+        Camera.Parameters p = mCamera.getParameters();
+
+        // Get preview resolutions
+
+        List<Camera.Size> unsortedSizes = p.getSupportedPreviewSizes();
+
+        class SizeCompare implements Comparator<Camera.Size> {
+            public int compare(Camera.Size lhs, Camera.Size rhs) {
+                if (lhs.width < rhs.width) return -1;
+                if (lhs.width > rhs.width) return 1;
+                if (lhs.height < rhs.height) return -1;
+                if (lhs.height > rhs.height) return 1;
+                return 0;
+            }
+        };
+
+        SizeCompare s = new SizeCompare();
+        TreeSet<Camera.Size> sortedResolutions = new TreeSet<Camera.Size>(s);
+        sortedResolutions.addAll(unsortedSizes);
+
+        mPreviewSizes = new ArrayList<Camera.Size>(sortedResolutions);
+
+        String[] availableSizeNames = new String[mPreviewSizes.size()];
+        for (int i = 0; i < mPreviewSizes.size(); i++) {
+            availableSizeNames[i] =
+                    Integer.toString(mPreviewSizes.get(i).width) + " x " +
+                    Integer.toString(mPreviewSizes.get(i).height);
+        }
+        mResolutionSpinner.setAdapter(
+            new ArrayAdapter<String>(
+                this, R.layout.cf_format_list_item, availableSizeNames));
+
+
+        // Set initial values
+
+        mNextPreviewSize = mPreviewSizes.get(0);
+        mResolutionSpinner.setSelection(0);
+
+        if (mPreviewTexture != null) {
+            startPreview();
+        }
+    }
+
+    private void shutdownCamera() {
+        if (mCamera != null) {
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+            mCamera.release();
+            mCamera = null;
+            mState = STATE_OFF;
+        }
+    }
+
+    private void startPreview() {
+        if (mState != STATE_OFF) {
+            // Stop for a while to drain callbacks
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+            mState = STATE_OFF;
+            Handler h = new Handler();
+            Runnable mDelayedPreview = new Runnable() {
+                public void run() {
+                    startPreview();
+                }
+            };
+            h.postDelayed(mDelayedPreview, 300);
+            return;
+        }
+        mState = STATE_PREVIEW;
+
+        Matrix transform = new Matrix();
+        float widthRatio = mNextPreviewSize.width / (float)mPreviewTexWidth;
+        float heightRatio = mNextPreviewSize.height / (float)mPreviewTexHeight;
+
+        transform.setScale(1, heightRatio/widthRatio);
+        transform.postTranslate(0,
+                mPreviewTexHeight * (1 - heightRatio/widthRatio)/2);
+
+        mPreviewView.setTransform(transform);
+
+        mPreviewSize   = mNextPreviewSize;
+
+        Camera.Parameters p = mCamera.getParameters();
+        p.setPreviewFormat(ImageFormat.NV21);
+        p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+        mCamera.setParameters(p);
+
+        mCamera.setPreviewCallbackWithBuffer(this);
+        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
+                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
+        for (int i=0; i < 4; i++) {
+            mCamera.addCallbackBuffer(new byte[expectedBytes]);
+        }
+        //mFormatView.setColorFilter(mYuv2RgbFilter);
+
+        mProcessingFirstFrame = true;
+        try {
+            mCamera.setPreviewTexture(mPreviewTexture);
+            mCamera.startPreview();
+        } catch (IOException ioe) {
+            // Something bad happened
+            Log.e(TAG, "Unable to start up preview");
+        }
+
+    }
+
+
+    private class ProcessPreviewDataTask extends AsyncTask<byte[], Void, Boolean> {
+        protected Boolean doInBackground(byte[]... datas) {
+            byte[] data = datas[0];
+
+            long t1 = java.lang.System.currentTimeMillis();
+
+            mFilterYuv.execute(data);
+            mFilterYuv.copyOut(mCallbackBitmap);
+
+            long t2 = java.lang.System.currentTimeMillis();
+            mTiming[mTimingSlot++] = t2 - t1;
+            if (mTimingSlot >= mTiming.length) {
+                float total = 0;
+                for (int i=0; i<mTiming.length; i++) {
+                    total += (float)mTiming[i];
+                }
+                total /= mTiming.length;
+                Log.e(TAG, "time + " + total);
+                mTimingSlot = 0;
+            }
+
+            mCamera.addCallbackBuffer(data);
+            mProcessInProgress = false;
+            return true;
+        }
+
+        protected void onPostExecute(Boolean result) {
+            mFormatView.invalidate();
+        }
+
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    public void onPreviewFrame(byte[] data, Camera camera) {
+        if (mProcessInProgress || mState != STATE_PREVIEW) {
+            mCamera.addCallbackBuffer(data);
+            return;
+        }
+        if (data == null) {
+            return;
+        }
+
+        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
+                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
+
+        if (expectedBytes != data.length) {
+            Log.e(TAG, "Mismatched size of buffer! Expected ");
+
+            mState = STATE_NO_CALLBACKS;
+            mCamera.setPreviewCallbackWithBuffer(null);
+            return;
+        }
+
+        mProcessInProgress = true;
+
+        if (mCallbackBitmap == null ||
+                mPreviewSize.width != mCallbackBitmap.getWidth() ||
+                mPreviewSize.height != mCallbackBitmap.getHeight() ) {
+            mCallbackBitmap =
+                    Bitmap.createBitmap(
+                        mPreviewSize.width, mPreviewSize.height,
+                        Bitmap.Config.ARGB_8888);
+            mFilterYuv = new RsYuv(mRS, getResources(), mPreviewSize.width, mPreviewSize.height);
+            mFormatView.setImageBitmap(mCallbackBitmap);
+        }
+
+
+        mFormatView.invalidate();
+
+        mCamera.addCallbackBuffer(data);
+        mProcessInProgress = true;
+        new ProcessPreviewDataTask().execute(data);
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
new file mode 100644
index 0000000..cced198
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.livepreview;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.graphics.SurfaceTexture;
+import android.renderscript.Allocation;
+import android.renderscript.Matrix3f;
+import android.renderscript.RenderScript;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+import android.graphics.Bitmap;
+
+public class RsYuv
+{
+    private int mHeight;
+    private int mWidth;
+    private RenderScript mRS;
+    private Allocation mAllocationOut;
+    private Allocation mAllocationIn;
+    private ScriptC_yuv mScript;
+
+    RsYuv(RenderScript rs, Resources res, int width, int height) {
+        mHeight = height;
+        mWidth = width;
+        mRS = rs;
+        mScript = new ScriptC_yuv(mRS, res, R.raw.yuv);
+        mScript.invoke_setSize(mWidth, mHeight);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+
+        mAllocationOut = Allocation.createTyped(rs, tb.create());
+        mAllocationIn = Allocation.createSized(rs, Element.U8(mRS), (mHeight * mWidth) +
+                                               ((mHeight / 2) * (mWidth / 2) * 2));
+
+        mScript.bind_gYuvIn(mAllocationIn);
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    void execute(byte[] yuv) {
+        mAllocationIn.copyFrom(yuv);
+        mRS.finish();
+
+        long t1 = java.lang.System.currentTimeMillis();
+        mScript.forEach_root(mAllocationOut);
+        mRS.finish();
+        long t2 = java.lang.System.currentTimeMillis();
+
+        mTiming[mTimingSlot++] = t2 - t1;
+        if (mTimingSlot >= mTiming.length) {
+            float total = 0;
+            for (int i=0; i<mTiming.length; i++) {
+                total += (float)mTiming[i];
+            }
+            total /= mTiming.length;
+            Log.e("yuv", "core time = " + total);
+            mTimingSlot = 0;
+        }
+    }
+
+    void copyOut(Bitmap b) {
+        mAllocationOut.copyTo(b);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
new file mode 100644
index 0000000..6057eff
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
@@ -0,0 +1,132 @@
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.livepreview)
+#pragma rs_fp_relaxed
+
+uchar *gYuvIn;
+
+static int gWidth;
+static int gHeight;
+static uchar crossProcess_tableR[256];
+static uchar crossProcess_tableG[256];
+static uchar crossProcess_tableB[256];
+static uchar vignette_table[512];
+
+
+static float4 crossProcess(float4 color) {
+    float4 ncolor = 0.f;
+    float v;
+
+    if (color.r < 0.5f) {
+        v = color.r;
+        ncolor.r = 4.0f * v * v * v;
+    } else {
+        v = 1.0f - color.r;
+        ncolor.r = 1.0f - (4.0f * v * v * v);
+    }
+
+    if (color.g < 0.5f) {
+        v = color.g;
+        ncolor.g = 2.0f * v * v;
+    } else {
+        v = 1.0f - color.g;
+        ncolor.g = 1.0f - (2.0f * v * v);
+    }
+
+    ncolor.b = color.b * 0.5f + 0.25f;
+    ncolor.a = color.a;
+    return ncolor;
+}
+
+static uchar4 crossProcess_i(uchar4 color) {
+    uchar4 ncolor = color;
+    ncolor.r = crossProcess_tableR[color.r];
+    ncolor.g = crossProcess_tableG[color.g];
+    ncolor.b = crossProcess_tableB[color.b];
+    return ncolor;
+}
+
+
+float temp = 0.2f;
+static float4 colortemp(float4 color) {
+    float4 new_color = color;
+    float4 t = color * ((float4)1.0f - color) * temp;
+
+    new_color.r = color.r + t.r;
+    new_color.b = color.b - t.b;
+    if (temp > 0.0f) {
+        color.g = color.g + t.g * 0.25f;
+    }
+    float max_value = max(new_color.r, max(new_color.g, new_color.b));
+    if (max_value > 1.0f) {
+        new_color /= max_value;
+    }
+
+    return new_color;
+}
+
+
+static float vignette_dist_mod;
+int2 vignette_half_dims;
+static uchar4 vignette(uchar4 color, uint32_t x, uint32_t y) {
+    int2 xy = {x, y};
+    xy -= vignette_half_dims;
+    xy *= xy;
+
+    float d = vignette_dist_mod * (xy.x + xy.y);
+    ushort4 c = convert_ushort4(color);
+    c *= vignette_table[(int)d];
+    c >>= (ushort4)8;
+    return convert_uchar4(c);
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uchar Y = gYuvIn[(y * gWidth) + x];
+    uchar *uv = &gYuvIn[gWidth * gHeight];
+    uv += (((x>>1)<<1) + (y>>1) * gWidth);
+
+    uchar4 p = rsYuvToRGBA_uchar4(Y, uv[1], uv[0]);
+    p = crossProcess_i(p);
+    p = vignette(p, x, y);
+
+    out->rgba = p;
+    out->a = 0xff;
+}
+
+float vignetteScale = 0.5f;
+float vignetteShade = 0.85f;
+
+static void precompute() {
+    for(int i=0; i <256; i++) {
+        float4 f = ((float)i) / 255.f;
+        float4 res = crossProcess(f);
+        res = colortemp(res);
+        crossProcess_tableR[i] = (uchar)(res.r * 255.f);
+        crossProcess_tableG[i] = (uchar)(res.g * 255.f);
+        crossProcess_tableB[i] = (uchar)(res.b * 255.f);
+    }
+
+    for(int i=0; i <512; i++) {
+        const float slope = 20.0f;
+        float f = ((float)i) / 511.f;
+
+        float range = 1.30f - sqrt(vignetteScale) * 0.7f;
+        float lumen = vignetteShade / (1.0f + exp((sqrt(f) - range) * slope)) + (1.0f - vignetteShade);
+        lumen = clamp(lumen, 0.f, 1.f);
+
+        vignette_table[i] = (uchar)(lumen * 255.f + 0.5f);
+    }
+}
+
+void init() {
+    precompute();
+}
+
+void setSize(int w, int h) {
+    gWidth = w;
+    gHeight = h;
+    vignette_half_dims = (int2){w / 2, h / 2};
+    vignette_dist_mod = 512.f;
+    vignette_dist_mod /= (float)(w*w + h*h) / 4.f;
+
+}
diff --git a/tests/RenderScriptTests/MiscSamples/Android.mk b/tests/RenderScriptTests/MiscSamples/Android.mk
index 6b8b691..bdff46a 100644
--- a/tests/RenderScriptTests/MiscSamples/Android.mk
+++ b/tests/RenderScriptTests/MiscSamples/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ModelViewer/Android.mk b/tests/RenderScriptTests/ModelViewer/Android.mk
index 1d9bacf..18ceac5 100644
--- a/tests/RenderScriptTests/ModelViewer/Android.mk
+++ b/tests/RenderScriptTests/ModelViewer/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
diff --git a/tests/RenderScriptTests/SampleTest/Android.mk b/tests/RenderScriptTests/SampleTest/Android.mk
index 7d74c55..f3439b0 100644
--- a/tests/RenderScriptTests/SampleTest/Android.mk
+++ b/tests/RenderScriptTests/SampleTest/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/SceneGraph/Android.mk b/tests/RenderScriptTests/SceneGraph/Android.mk
index ba4b3c5..163a95d 100644
--- a/tests/RenderScriptTests/SceneGraph/Android.mk
+++ b/tests/RenderScriptTests/SceneGraph/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ShadersTest/Android.mk b/tests/RenderScriptTests/ShadersTest/Android.mk
index 109b0a0..0912591 100644
--- a/tests/RenderScriptTests/ShadersTest/Android.mk
+++ b/tests/RenderScriptTests/ShadersTest/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/SurfaceTexture/Android.mk b/tests/RenderScriptTests/SurfaceTexture/Android.mk
index bbd4d55..d5262ee2 100644
--- a/tests/RenderScriptTests/SurfaceTexture/Android.mk
+++ b/tests/RenderScriptTests/SurfaceTexture/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/tests/Android.mk b/tests/RenderScriptTests/tests/Android.mk
index 880b80f..198693c 100644
--- a/tests/RenderScriptTests/tests/Android.mk
+++ b/tests/RenderScriptTests/tests/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index d0f3e62..36f13b1 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -84,6 +84,7 @@
         unitTests.add(new UT_struct(this, mRes, mCtx));
         unitTests.add(new UT_math(this, mRes, mCtx));
         unitTests.add(new UT_math_conformance(this, mRes, mCtx));
+        unitTests.add(new UT_math_agree(this, mRes, mCtx));
         unitTests.add(new UT_element(this, mRes, mCtx));
         unitTests.add(new UT_sampler(this, mRes, mCtx));
         unitTests.add(new UT_program_store(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..9d94ba5
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,548 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Random;
+
+public class UT_math_agree extends UnitTest {
+    private Resources mRes;
+    private Random rand;
+
+    protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Agreement", ctx);
+        mRes = res;
+        rand = new Random();
+    }
+
+    // packing functions
+    private Float2 pack_f2(float[] val) {
+        assert val.length == 2;
+        return new Float2(val[0], val[1]);
+    }
+    private Float3 pack_f3(float[] val) {
+        assert val.length == 3;
+        return new Float3(val[0], val[1], val[2]);
+    }
+    private Float4 pack_f4(float[] val) {
+        assert val.length == 4;
+        return new Float4(val[0], val[1], val[2], val[3]);
+    }
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        return new Byte2(val[0], val[1]);
+    }
+    private Byte3 pack_b3(byte[] val) {
+        assert val.length == 3;
+        return new Byte3(val[0], val[1], val[2]);
+    }
+    private Byte4 pack_b4(byte[] val) {
+        assert val.length == 4;
+        return new Byte4(val[0], val[1], val[2], val[3]);
+    }
+    private Short2 pack_s2(short[] val) {
+        assert val.length == 2;
+        return new Short2(val[0], val[1]);
+    }
+    private Short3 pack_s3(short[] val) {
+        assert val.length == 3;
+        return new Short3(val[0], val[1], val[2]);
+    }
+    private Short4 pack_s4(short[] val) {
+        assert val.length == 4;
+        return new Short4(val[0], val[1], val[2], val[3]);
+    }
+    private Int2 pack_i2(int[] val) {
+        assert val.length == 2;
+        return new Int2(val[0], val[1]);
+    }
+    private Int3 pack_i3(int[] val) {
+        assert val.length == 3;
+        return new Int3(val[0], val[1], val[2]);
+    }
+    private Int4 pack_i4(int[] val) {
+        assert val.length == 4;
+        return new Int4(val[0], val[1], val[2], val[3]);
+    }
+    private Long2 pack_l2(long[] val) {
+        assert val.length == 2;
+        return new Long2(val[0], val[1]);
+    }
+    private Long3 pack_l3(long[] val) {
+        assert val.length == 3;
+        return new Long3(val[0], val[1], val[2]);
+    }
+    private Long4 pack_l4(long[] val) {
+        assert val.length == 4;
+        return new Long4(val[0], val[1], val[2], val[3]);
+    }
+
+    // random vector generation functions
+    private float[] randvec_float(int dim) {
+        float[] fv = new float[dim];
+        for (int i = 0; i < dim; ++i)
+            fv[i] = rand.nextFloat();
+        return fv;
+    }
+    private byte[] randvec_char(int dim) {
+        byte[] cv = new byte[dim];
+        rand.nextBytes(cv);
+        return cv;
+    }
+    private short[] randvec_uchar(int dim) {
+       short[] ucv = new short[dim];
+       for (int i = 0; i < dim; ++i)
+           ucv[i] = (short)rand.nextInt(0x1 << 8);
+       return ucv;
+    }
+    private short[] randvec_short(int dim) {
+        short[] sv = new short[dim];
+        for (int i = 0; i < dim; ++i)
+            sv[i] = (short)rand.nextInt(0x1 << 16);
+        return sv;
+    }
+    private int[] randvec_ushort(int dim) {
+        int[] usv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            usv[i] = rand.nextInt(0x1 << 16);
+        return usv;
+    }
+    private int[] randvec_int(int dim) {
+        int[] iv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            iv[i] = rand.nextInt();
+        return iv;
+    }
+    private long[] randvec_uint(int dim) {
+        long[] uiv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        return uiv;
+    }
+    private long[] randvec_long(int dim) {
+        long[] lv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            lv[i] = rand.nextLong();
+        return lv;
+    }
+    // TODO:  unsigned long generator
+
+    // min reference functions
+    private float min(float v1, float v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private float[] min(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private short min(short v1, short v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private short[] min(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private int min(int v1, int v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private int[] min(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private long min(long v1, long v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private long[] min(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of min
+
+    // max reference functions
+    private float max(float v1, float v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private float[] max(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private byte max(byte v1, byte v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private byte[] max(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private short max(short v1, short v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private short[] max(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private int max(int v1, int v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private int[] max(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private long max(long v1, long v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private long[] max(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of max
+
+    // fmin reference functions
+    private float fmin(float v1, float v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float[] v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2);
+        return rv;
+    }
+
+    // fmax reference functions
+    private float fmax(float v1, float v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float[] v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_math_agree s) {
+        float x = rand.nextFloat();
+        float y = rand.nextFloat();
+
+        s.set_x(x);
+        s.set_y(y);
+        s.set_result_add(x + y);
+        s.set_result_sub(x - y);
+        s.set_result_mul(x * y);
+        s.set_result_div(x / y);
+
+        // Generate random vectors of all types
+        float rand_f1_0 = rand.nextFloat();
+        float[] rand_f2_0 = randvec_float(2);
+        float[] rand_f3_0 = randvec_float(3);
+        float[] rand_f4_0 = randvec_float(4);
+        float rand_f1_1 = rand.nextFloat();
+        float[] rand_f2_1 = randvec_float(2);
+        float[] rand_f3_1 = randvec_float(3);
+        float[] rand_f4_1 = randvec_float(4);
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        // FIXME:  generate unsigned input vectors once bug 6764163 is fixed
+        /*
+        short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_0 = randvec_uchar(2);
+        short[] rand_uc3_0 = randvec_uchar(3);
+        short[] rand_uc4_0 = randvec_uchar(4);
+        short rand_uc1_1 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_1 = randvec_uchar(2);
+        short[] rand_uc3_1 = randvec_uchar(3);
+        short[] rand_uc4_1 = randvec_uchar(4);
+        int rand_us1_0 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_0 = randvec_ushort(2);
+        int[] rand_us3_0 = randvec_ushort(3);
+        int[] rand_us4_0 = randvec_ushort(4);
+        int rand_us1_1 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_1 = randvec_ushort(2);
+        int[] rand_us3_1 = randvec_ushort(3);
+        int[] rand_us4_1 = randvec_ushort(4);
+        long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_0 = randvec_uint(2);
+        long[] rand_ui3_0 = randvec_uint(3);
+        long[] rand_ui4_0 = randvec_uint(4);
+        long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_1 = randvec_uint(2);
+        long[] rand_ui3_1 = randvec_uint(3);
+        long[] rand_ui4_1 = randvec_uint(4);
+        */
+        // TODO:  generate unsigned long vectors
+
+        // Set random vectors in renderscript code
+        s.set_rand_f1_0(rand_f1_0);
+        s.set_rand_f2_0(pack_f2(rand_f2_0));
+        s.set_rand_f3_0(pack_f3(rand_f3_0));
+        s.set_rand_f4_0(pack_f4(rand_f4_0));
+        s.set_rand_f1_1(rand_f1_1);
+        s.set_rand_f2_1(pack_f2(rand_f2_1));
+        s.set_rand_f3_1(pack_f3(rand_f3_1));
+        s.set_rand_f4_1(pack_f4(rand_f4_1));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        s.set_rand_ss1_0(rand_ss1_0);
+        s.set_rand_ss2_0(pack_s2(rand_ss2_0));
+        s.set_rand_ss3_0(pack_s3(rand_ss3_0));
+        s.set_rand_ss4_0(pack_s4(rand_ss4_0));
+        s.set_rand_ss1_1(rand_ss1_1);
+        s.set_rand_ss2_1(pack_s2(rand_ss2_1));
+        s.set_rand_ss3_1(pack_s3(rand_ss3_1));
+        s.set_rand_ss4_1(pack_s4(rand_ss4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        // FIXME:  set signed char input vectors once bug is fixed
+        /*
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        */
+        // FIXME:  set unsigned input vectors once bug 6764163 is fixed
+        /*
+        s.set_rand_us1_0(rand_us1_0);
+        s.set_rand_us2_0(pack_i2(rand_us2_0));
+        s.set_rand_us3_0(pack_i3(rand_us3_0));
+        s.set_rand_us4_0(pack_i4(rand_us4_0));
+        s.set_rand_us1_1(rand_us1_1);
+        s.set_rand_us2_1(pack_i2(rand_us2_1));
+        s.set_rand_us3_1(pack_i3(rand_us3_1));
+        s.set_rand_us4_1(pack_i4(rand_us4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_ui1_0(rand_ui1_0);
+        s.set_rand_ui2_0(pack_l2(rand_ui2_0));
+        s.set_rand_ui3_0(pack_l3(rand_ui3_0));
+        s.set_rand_ui4_0(pack_l4(rand_ui4_0));
+        s.set_rand_ui1_1(rand_ui1_1);
+        s.set_rand_ui2_1(pack_l2(rand_ui2_1));
+        s.set_rand_ui3_1(pack_l3(rand_ui3_1));
+        s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        */
+        // TODO:  set unsigned long vectors
+
+        // Set results for min
+        s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1));
+        s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
+        s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
+        s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
+        s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
+        s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
+        s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
+        s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
+        s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
+        s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
+        s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
+        s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
+        s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
+        // FIXME:  set signed char min reference vectors once bug is fixed
+        /*
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
+        s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
+        s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
+        */
+        // FIXME:  set unsigned min reference vectors once bug 6764163 is fixed
+        /*
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s3(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
+        */
+        // TODO:  set results for unsigned long min
+
+        // Set results for max
+        s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1));
+        s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
+        s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
+        s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
+        s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
+        s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
+        s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
+        s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
+        s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
+        s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
+        s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
+        s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
+        s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
+        // FIXME:  set signed char max reference vectors once bug is fixed
+        /*
+        s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
+        s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
+        s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
+        s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
+        */
+        // FIXME:  set unsigned max reference vectors once bug 6764163 is fixed
+        /*
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s3(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
+        */
+        // TODO:  set results for unsigned long max
+
+        // Set results for fmin
+        s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1));
+        s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1)));
+        s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1)));
+        s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1)));
+        s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1)));
+        s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1)));
+        s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1)));
+
+        // Set results for fmax
+        s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1));
+        s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1)));
+        s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1)));
+        s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1)));
+        s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1)));
+        s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1)));
+        s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1)));
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_agree s = new ScriptC_math_agree(pRS, mRes,
+                R.raw.math_agree);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_math_agree_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..ac3a3fa
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,411 @@
+#include "shared.rsh"
+//#pragma rs_fp_relaxed
+
+volatile float x = 0.0f;
+volatile float y = 0.0f;
+volatile float result_add = 0.0f;
+volatile float result_sub = 0.0f;
+volatile float result_mul = 0.0f;
+volatile float result_div = 0.0f;
+
+#define DECLARE_INPUT_SET(type, abbrev)         \
+volatile type    rand_##abbrev##1_0, rand_##abbrev##1_1; \
+volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \
+volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \
+volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1;
+
+#define DECLARE_ALL_INPUT_SETS()    \
+DECLARE_INPUT_SET(float, f);        \
+DECLARE_INPUT_SET(char, sc);        \
+DECLARE_INPUT_SET(uchar, uc);       \
+DECLARE_INPUT_SET(short, ss);       \
+DECLARE_INPUT_SET(ushort, us);      \
+DECLARE_INPUT_SET(int, si);         \
+DECLARE_INPUT_SET(uint, ui);        \
+DECLARE_INPUT_SET(long, sl);        \
+DECLARE_INPUT_SET(ulong, ul);
+
+DECLARE_ALL_INPUT_SETS();
+
+#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func)   \
+volatile type    func##_rand_##abbrev##1_##abbrev##1;                \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##2;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##3;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##4;
+#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func)   \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##1;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##1;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##1;
+
+#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func)    \
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func);    \
+DECLARE_REFERENCE_SET_VEC_VEC(int, si, func);       \
+DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func);
+
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min);
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax);
+
+static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) {
+    int dist = float_dist(actual, expected);
+    rsDebug("float operation did not match!", op_name);
+    rsDebug("v1", v1);
+    rsDebug("v2", v2);
+    rsDebug("Dalvik result", expected);
+    rsDebug("Renderscript result", actual);
+    rsDebug("ULP difference", dist);
+}
+
+static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) {
+    int2 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    rsDebug("float2 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+}
+
+static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) {
+    int3 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    rsDebug("float3 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+}
+
+static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) {
+    int4 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    dist.w = float_dist(actual.w, expected.w);
+    rsDebug("float4 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v1.w", v1.w);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("v2.w", v2.w);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Dalvik result .w", expected.w);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("Renderscript result .w", actual.w);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+    rsDebug("ULP difference .w", dist.w);
+}
+
+static bool f1_almost_equal(float a, float b) {
+    return float_almost_equal(a, b);
+}
+
+static bool f2_almost_equal(float2 a, float2 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y);
+}
+
+
+static bool f3_almost_equal(float3 a, float3 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z);
+}
+
+static bool f4_almost_equal(float4 a, float4 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w);
+}
+
+#define TEST_BASIC_FLOAT_OP(op, opName)                 \
+temp_f1 = x op y;                                       \
+if (! float_almost_equal(temp_f1, result_##opName)) {   \
+    fail_f1(x, y , temp_f1, result_##opName, #opName);  \
+    failed = true;                                      \
+}
+
+#define TEST_FN_FN(func, size)                                                  \
+temp_f##size = func(rand_f##size##_0, rand_f##size##_1);                        \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) {   \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func);   \
+    failed = true;                                                              \
+}
+#define TEST_FN_F(func, size)                                               \
+temp_f##size = func(rand_f##size##_0, rand_f1_1);                           \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) {    \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func);   \
+    failed = true;                                                          \
+}
+
+#define TEST_FN_FN_ALL(func)    \
+TEST_FN_FN(func, 1)             \
+TEST_FN_FN(func, 2)             \
+TEST_FN_FN(func, 3)             \
+TEST_FN_FN(func, 4)
+#define TEST_FN_F_ALL(func) \
+TEST_FN_F(func, 2)          \
+TEST_FN_F(func, 3)          \
+TEST_FN_F(func, 4)
+
+#define TEST_VEC1_VEC1(func, type)                              \
+temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 );    \
+if (temp_##type##1 != func##_rand_##type##1_##type##1) {        \
+    rsDebug(#func " " #type "1 operation did not match!", 0);   \
+    rsDebug("v1", rand_##type##1_0);                            \
+    rsDebug("v2", rand_##type##1_1);                            \
+    rsDebug("Dalvik result", func##_rand_##type##1_##type##1);  \
+    rsDebug("Renderscript result", temp_##type##1);             \
+    failed = true;                                              \
+}
+#define TEST_VEC2_VEC2(func, type)                                      \
+temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 );            \
+if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x             \
+        || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) {   \
+    rsDebug(#func " " #type "2 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##2_0 .x);                               \
+    rsDebug("v1.y", rand_##type##2_0 .y);                               \
+    rsDebug("v2.x", rand_##type##2_1 .x);                               \
+    rsDebug("v2.y", rand_##type##2_1 .y);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y);    \
+    rsDebug("Renderscript result .x", temp_##type##2 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##2 .y);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC3_VEC3(func, type)                                      \
+temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 );            \
+if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x             \
+        || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y      \
+        || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) {   \
+    rsDebug(#func " " #type "3 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##3_0 .x);                               \
+    rsDebug("v1.y", rand_##type##3_0 .y);                               \
+    rsDebug("v1.z", rand_##type##3_0 .z);                               \
+    rsDebug("v2.x", rand_##type##3_1 .x);                               \
+    rsDebug("v2.y", rand_##type##3_1 .y);                               \
+    rsDebug("v2.z", rand_##type##3_1 .z);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z);    \
+    rsDebug("Renderscript result .x", temp_##type##3 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##3 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##3 .z);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC4_VEC4(func, type)                                      \
+temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 );            \
+if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x             \
+        || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y      \
+        || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z      \
+        || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) {   \
+    rsDebug(#func " " #type "4 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##4_0 .x);                               \
+    rsDebug("v1.y", rand_##type##4_0 .y);                               \
+    rsDebug("v1.z", rand_##type##4_0 .z);                               \
+    rsDebug("v1.w", rand_##type##4_0 .w);                               \
+    rsDebug("v2.x", rand_##type##4_1 .x);                               \
+    rsDebug("v2.y", rand_##type##4_1 .y);                               \
+    rsDebug("v2.z", rand_##type##4_1 .z);                               \
+    rsDebug("v2.w", rand_##type##4_1 .w);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z);    \
+    rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w);    \
+    rsDebug("Renderscript result .x", temp_##type##4 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##4 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##4 .z);               \
+    rsDebug("Renderscript result .w", temp_##type##4 .w);               \
+    failed = true;                                                      \
+}
+
+#define TEST_SC1_SC1(func)  TEST_VEC1_VEC1(func, sc)
+#define TEST_SC2_SC2(func)  TEST_VEC2_VEC2(func, sc)
+#define TEST_SC3_SC3(func)  TEST_VEC3_VEC3(func, sc)
+#define TEST_SC4_SC4(func)  TEST_VEC4_VEC4(func, sc)
+
+#define TEST_UC1_UC1(func)  TEST_VEC1_VEC1(func, uc)
+#define TEST_UC2_UC2(func)  TEST_VEC2_VEC2(func, uc)
+#define TEST_UC3_UC3(func)  TEST_VEC3_VEC3(func, uc)
+#define TEST_UC4_UC4(func)  TEST_VEC4_VEC4(func, uc)
+
+#define TEST_SS1_SS1(func)  TEST_VEC1_VEC1(func, ss)
+#define TEST_SS2_SS2(func)  TEST_VEC2_VEC2(func, ss)
+#define TEST_SS3_SS3(func)  TEST_VEC3_VEC3(func, ss)
+#define TEST_SS4_SS4(func)  TEST_VEC4_VEC4(func, ss)
+
+#define TEST_US1_US1(func)  TEST_VEC1_VEC1(func, us)
+#define TEST_US2_US2(func)  TEST_VEC2_VEC2(func, us)
+#define TEST_US3_US3(func)  TEST_VEC3_VEC3(func, us)
+#define TEST_US4_US4(func)  TEST_VEC4_VEC4(func, us)
+
+#define TEST_SI1_SI1(func)  TEST_VEC1_VEC1(func, si)
+#define TEST_SI2_SI2(func)  TEST_VEC2_VEC2(func, si)
+#define TEST_SI3_SI3(func)  TEST_VEC3_VEC3(func, si)
+#define TEST_SI4_SI4(func)  TEST_VEC4_VEC4(func, si)
+
+#define TEST_UI1_UI1(func)  TEST_VEC1_VEC1(func, ui)
+#define TEST_UI2_UI2(func)  TEST_VEC2_VEC2(func, ui)
+#define TEST_UI3_UI3(func)  TEST_VEC3_VEC3(func, ui)
+#define TEST_UI4_UI4(func)  TEST_VEC4_VEC4(func, ui)
+
+#define TEST_SL1_SL1(func)  TEST_VEC1_VEC1(func, sl)
+#define TEST_SL2_SL2(func)  TEST_VEC2_VEC2(func, sl)
+#define TEST_SL3_SL3(func)  TEST_VEC3_VEC3(func, sl)
+#define TEST_SL4_SL4(func)  TEST_VEC4_VEC4(func, sl)
+
+#define TEST_UL1_UL1(func)  TEST_VEC1_VEC1(func, ul)
+#define TEST_UL2_UL2(func)  TEST_VEC2_VEC2(func, ul)
+#define TEST_UL3_UL3(func)  TEST_VEC3_VEC3(func, ul)
+#define TEST_UL4_UL4(func)  TEST_VEC4_VEC4(func, ul)
+
+#define TEST_SC_SC_ALL(func)    \
+TEST_SC1_SC1(func)              \
+TEST_SC2_SC2(func)              \
+TEST_SC3_SC3(func)              \
+TEST_SC4_SC4(func)
+#define TEST_UC_UC_ALL(func)    \
+TEST_UC1_UC1(func)              \
+TEST_UC2_UC2(func)              \
+TEST_UC3_UC3(func)              \
+TEST_UC4_UC4(func)
+
+#define TEST_SS_SS_ALL(func)    \
+TEST_SS1_SS1(func)              \
+TEST_SS2_SS2(func)              \
+TEST_SS3_SS3(func)              \
+TEST_SS4_SS4(func)
+#define TEST_US_US_ALL(func)    \
+TEST_US1_US1(func)              \
+TEST_US2_US2(func)              \
+TEST_US3_US3(func)              \
+TEST_US4_US4(func)
+#define TEST_SI_SI_ALL(func)    \
+TEST_SI1_SI1(func)              \
+TEST_SI2_SI2(func)              \
+TEST_SI3_SI3(func)              \
+TEST_SI4_SI4(func)
+#define TEST_UI_UI_ALL(func)    \
+TEST_UI1_UI1(func)              \
+TEST_UI2_UI2(func)              \
+TEST_UI3_UI3(func)              \
+TEST_UI4_UI4(func)
+#define TEST_SL_SL_ALL(func)    \
+TEST_SL1_SL1(func)              \
+TEST_SL2_SL2(func)              \
+TEST_SL3_SL3(func)              \
+TEST_SL4_SL4(func)
+#define TEST_UL_UL_ALL(func)    \
+TEST_UL1_UL1(func)              \
+TEST_UL2_UL2(func)              \
+TEST_UL3_UL3(func)              \
+TEST_UL4_UL4(func)
+
+#define TEST_VEC_VEC_ALL(func)  \
+TEST_FN_FN_ALL(func)              \
+TEST_SS_SS_ALL(func)            \
+TEST_SI_SI_ALL(func)
+// FIXME:  Add tests back in once bug 6764163 is fixed
+#if 0
+TEST_SC_SC_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_UC_UC_ALL(func)            \
+TEST_UI_UI_ALL(func)
+#endif
+// TODO:  add long types to ALL macro
+#if 0
+TEST_SL_SL_ALL(func)            \
+TEST_UL_UL_ALL(func)
+#endif
+
+#define DECLARE_TEMP_SET(type, abbrev)  \
+volatile type    temp_##abbrev##1;               \
+volatile type##2 temp_##abbrev##2;               \
+volatile type##3 temp_##abbrev##3;               \
+volatile type##4 temp_##abbrev##4;
+
+#define DECLARE_ALL_TEMP_SETS() \
+DECLARE_TEMP_SET(float, f);     \
+DECLARE_TEMP_SET(char, sc);     \
+DECLARE_TEMP_SET(uchar, uc);    \
+DECLARE_TEMP_SET(short, ss);    \
+DECLARE_TEMP_SET(ushort, us);   \
+DECLARE_TEMP_SET(int, si);      \
+DECLARE_TEMP_SET(uint, ui);     \
+DECLARE_TEMP_SET(long, sl);     \
+DECLARE_TEMP_SET(ulong, ul);
+
+static bool test_math_agree() {
+    bool failed = false;
+
+    DECLARE_ALL_TEMP_SETS();
+
+    TEST_BASIC_FLOAT_OP(+, add);
+    TEST_BASIC_FLOAT_OP(-, sub);
+    TEST_BASIC_FLOAT_OP(*, mul);
+    TEST_BASIC_FLOAT_OP(/, div);
+
+    TEST_VEC_VEC_ALL(min);
+    TEST_VEC_VEC_ALL(max);
+    TEST_FN_FN_ALL(fmin);
+    TEST_FN_F_ALL(fmin);
+    TEST_FN_FN_ALL(fmax);
+    TEST_FN_F_ALL(fmax);
+
+    if (failed) {
+        rsDebug("test_math_agree FAILED", 0);
+    }
+    else {
+        rsDebug("test_math_agree PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_agree_test() {
+    bool failed = false;
+    failed |= test_math_agree();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs
index f7942a5..68ac168 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs
@@ -2,6 +2,9 @@
 
 // Testing primitive types
 float floatTest = 1.99f;
+float2 float2Test = {2.99f, 12.99f};
+float3 float3Test = {3.99f, 13.99f, 23.99f};
+float4 float4Test = {4.99f, 14.99f, 24.99f, 34.99f};
 double doubleTest = 2.05;
 char charTest = -8;
 short shortTest = -16;
@@ -23,6 +26,9 @@
     // For this reason, none of the outputs are actually checked.
 
     rsDebug("floatTest", floatTest);
+    rsDebug("float2Test", float2Test);
+    rsDebug("float3Test", float3Test);
+    rsDebug("float4Test", float4Test);
     rsDebug("doubleTest", doubleTest);
     rsDebug("charTest", charTest);
     rsDebug("shortTest", shortTest);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh b/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh
index 8cdf0d8..3adc999 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh
@@ -74,6 +74,40 @@
     return isposzero(f) || isnegzero(f);
 }
 
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
 /* These constants must match those in UnitTest.java */
 static const int RS_MSG_TEST_PASSED = 100;
 static const int RS_MSG_TEST_FAILED = 101;
diff --git a/tests/RenderScriptTests/tests_v11/Android.mk b/tests/RenderScriptTests/tests_v11/Android.mk
index 93a429b..52d326b 100644
--- a/tests/RenderScriptTests/tests_v11/Android.mk
+++ b/tests/RenderScriptTests/tests_v11/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/tests_v14/Android.mk b/tests/RenderScriptTests/tests_v14/Android.mk
index c4c3a37..a4386a44 100644
--- a/tests/RenderScriptTests/tests_v14/Android.mk
+++ b/tests/RenderScriptTests/tests_v14/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeChildFrameTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeChildFrameTest.java
new file mode 100644
index 0000000..3f0e2b3
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeChildFrameTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge.
+ *
+ * Ensures that injected objects are exposed to child frames as well as the
+ * main frame.
+ *
+ * To run this test ...
+ *  adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeChildFrameTest \
+ *          com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeChildFrameTest extends JavaBridgeTestBase {
+    private class TestController extends Controller {
+        private String mStringValue;
+
+       public synchronized void setStringValue(String x) {
+            mStringValue = x;
+            notifyResultIsReady();
+        }
+       public synchronized String waitForStringValue() {
+            waitForResult();
+            return mStringValue;
+        }
+    }
+
+    TestController mTestController;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mTestController = new TestController();
+        setUpWebView(mTestController, "testController");
+    }
+
+    public void testInjectedObjectPresentInChildFrame() throws Throwable {
+        // In the case that the test fails (i.e. the child frame doesn't get the injected object,
+        // the call to testController.setStringValue in the child frame's onload handler will
+        // not be made.
+        getActivity().getWebView().loadData(
+                "<html><head></head><body>" +
+                "<iframe id=\"childFrame\" onload=\"testController.setStringValue('PASS');\" />" +
+                "</body></html>", "text/html", null);
+        assertEquals("PASS", mTestController.waitForStringValue());
+    }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
index 1af3f63..a451015 100644
--- a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
@@ -106,7 +106,12 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
-                getWebView().loadUrl("javascript:" + script);
+                // When a JavaScript URL is executed, if the value of the last
+                // expression evaluated is not 'undefined', this value is
+                // converted to a string and used as the new document for the
+                // frame. We don't want this behaviour, so wrap the script in
+                // an anonymous function.
+                getWebView().loadUrl("javascript:(function() { " + script + " })()");
             }
         });
     }
diff --git a/tools/aidl/generate_java_rpc.cpp b/tools/aidl/generate_java_rpc.cpp
index e5fa076..5e4dacc 100644
--- a/tools/aidl/generate_java_rpc.cpp
+++ b/tools/aidl/generate_java_rpc.cpp
@@ -786,7 +786,10 @@
     }
 
     // Call the callback method
-    dispatchMethod->statements->Add(realCall);
+    IfStatement* ifst = new IfStatement;
+        ifst->expression = new Comparison(new FieldVariable(THIS_VALUE, "callback"), "!=", NULL_VALUE);
+    dispatchMethod->statements->Add(ifst);
+    ifst->statements->Add(realCall);
 }
 
 static void
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index a5db7b1..3c124d9 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -2,10 +2,10 @@
 <classpath>
 	<classpathentry excluding="org/kxml2/io/" kind="src" path="src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/ninepatch/ninepatch-prebuilt.jar"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/tools-common/tools-common-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 379fb81..e28375d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -53,6 +53,11 @@
     }
 
     @Override
+    public void moved(int arg0, int arg1) throws RemoteException {
+        // pass for now.
+    }
+
+    @Override
     public void dispatchScreenState(boolean on) throws RemoteException {
         // pass for now.
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 8ab875f..3e56b60 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -23,6 +23,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
@@ -31,15 +32,11 @@
 import android.view.Display_Delegate;
 import android.view.Gravity;
 import android.view.IApplicationToken;
+import android.view.IInputFilter;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
 import android.view.IWindowManager;
 import android.view.IWindowSession;
-import android.view.InputChannel;
-import android.view.InputDevice;
-import android.view.InputEvent;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
 
 import java.util.List;
 
@@ -455,4 +452,27 @@
     public void lockNow() {
         // TODO Auto-generated method stub
     }
+
+    @Override
+    public IBinder getFocusedWindowToken() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean getWindowFrame(IBinder token, Rect outBounds) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public float getWindowCompatibilityScale(IBinder windowToken) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setInputFilter(IInputFilter filter) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 6fb599d..1d71e1b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -167,6 +167,12 @@
     }
 
     @Override
+    public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
+            float dsdx, float dtdx, float dsdy, float dtdy) {
+        // pass for now.
+    }
+
+    @Override
     public IBinder asBinder() {
         // pass for now.
         return null;
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 673a650..1579e6a 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -790,7 +790,7 @@
     if (AudioTrack::getMinFrameCount(&output, AUDIO_STREAM_VOICE_CALL,
         sampleRate) != NO_ERROR || output <= 0 ||
         AudioRecord::getMinFrameCount(&input, sampleRate,
-        AUDIO_FORMAT_PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
+        AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO) != NO_ERROR || input <= 0) {
         ALOGE("cannot compute frame count");
         return false;
     }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 84c24dd..75bd6e2 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -23,13 +23,8 @@
 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
 
 /**
- * TODO: Add soft AP states as part of WIFI_STATE_XXX
- * Retain WIFI_STATE_ENABLING that indicates driver is loading
- * Add WIFI_STATE_AP_ENABLED to indicate soft AP has started
- * and WIFI_STATE_FAILED for failure
+ * TODO:
  * Deprecate WIFI_STATE_UNKNOWN
- *
- * Doing this will simplify the logic for sending broadcasts
  */
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
@@ -94,13 +89,10 @@
  * Track the state of Wifi connectivity. All event handling is done here,
  * and all changes in connectivity state are initiated here.
  *
- * Wi-Fi now supports three modes of operation: Client, Soft Ap and Direct
- * In the current implementation, we do not support any concurrency and thus only
- * one of Client, Soft Ap or Direct operation is supported at any time.
- *
- * The WifiStateMachine supports Soft Ap and Client operations while WifiP2pService
- * handles Direct. WifiP2pService and WifiStateMachine co-ordinate to ensure only
- * one exists at a certain time.
+ * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p
+ * In the current implementation, we support concurrent wifi p2p and wifi operation.
+ * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService
+ * handles p2p operation.
  *
  * @hide
  */
@@ -110,9 +102,6 @@
     private static final String NETWORKTYPE = "WIFI";
     private static final boolean DBG = false;
 
-    /* TODO: This is no more used with the hostapd code. Clean up */
-    private static final String SOFTAP_IFACE = "wl0.1";
-
     private WifiMonitor mWifiMonitor;
     private WifiNative mWifiNative;
     private WifiConfigStore mWifiConfigStore;
@@ -1794,12 +1783,12 @@
         new Thread(new Runnable() {
             public void run() {
                 try {
-                    mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+                    mNwService.startAccessPoint(config, mInterfaceName);
                 } catch (Exception e) {
                     loge("Exception in softap start " + e);
                     try {
                         mNwService.stopAccessPoint(mInterfaceName);
-                        mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+                        mNwService.startAccessPoint(config, mInterfaceName);
                     } catch (Exception e1) {
                         loge("Exception in softap re-start " + e1);
                         sendMessage(CMD_START_AP_FAILURE);
@@ -3535,6 +3524,8 @@
                     if (DBG) log("Network connection lost");
                     handleNetworkDisconnect();
                     break;
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                    // EAP failures do not mean much during WPS
                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     //Throw away supplicant state changes when WPS is running.
                     //We will start getting supplicant state changes once we get
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 1a42f93..4018c74 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -170,9 +170,6 @@
     static final int RSSI_FETCH_SUCCEEDED                           = BASE + 24;
     static final int RSSI_FETCH_FAILED                              = BASE + 25;
 
-    private static final int SINGLE_ARP_CHECK = 0;
-    private static final int FULL_ARP_CHECK   = 1;
-
     private Context mContext;
     private ContentResolver mContentResolver;
     private WifiManager mWifiManager;
@@ -651,7 +648,9 @@
                     break;
                 case CMD_ARP_CHECK:
                     if (msg.arg1 == mArpToken) {
-                        if (doArpTest(FULL_ARP_CHECK) == true) {
+                        boolean success = ArpPeer.doArp(mWifiInfo.getMacAddress(), mLinkProperties,
+                                mArpPingTimeoutMs, mNumArpPings, mMinArpResponses);
+                        if (success) {
                             if (DBG) log("Notify link is good " + mCurrentSignalLevel);
                             mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
                         } else {
@@ -842,50 +841,6 @@
         return true;
     }
 
-    private boolean doArpTest(int type) {
-        boolean success;
-
-        String iface = mLinkProperties.getInterfaceName();
-        String mac = mWifiInfo.getMacAddress();
-        InetAddress inetAddress = null;
-        InetAddress gateway = null;
-
-        for (LinkAddress la : mLinkProperties.getLinkAddresses()) {
-            inetAddress = la.getAddress();
-            break;
-        }
-
-        for (RouteInfo route : mLinkProperties.getRoutes()) {
-            gateway = route.getGateway();
-            break;
-        }
-
-        if (DBG) log("ARP " + iface + "addr: " + inetAddress + "mac: " + mac + "gw: " + gateway);
-
-        try {
-            ArpPeer peer = new ArpPeer(iface, inetAddress, mac, gateway);
-            if (type == SINGLE_ARP_CHECK) {
-                success = (peer.doArp(mArpPingTimeoutMs) != null);
-                if (DBG) log("single ARP test result: " + success);
-            } else {
-                int responses = 0;
-                for (int i=0; i < mNumArpPings; i++) {
-                    if(peer.doArp(mArpPingTimeoutMs) != null) responses++;
-                }
-                if (DBG) log("full ARP test result: " + responses + "/" + mNumArpPings);
-                success = (responses >= mMinArpResponses);
-            }
-            peer.close();
-        } catch (SocketException se) {
-            //Consider an Arp socket creation issue as a successful Arp
-            //test to avoid any wifi connectivity issues
-            loge("ARP test initiation failure: " + se);
-            success = true;
-        }
-
-        return success;
-    }
-
     private int calculateSignalLevel(int rssi) {
         int signalLevel = WifiManager.calculateSignalLevel(rssi,
                 WifiManager.RSSI_LEVELS);
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 5759074..6978084 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1192,7 +1192,7 @@
                     }
 
                     if (mGroup.isGroupOwner()) {
-                        stopDhcpServer();
+                        stopDhcpServer(mGroup.getInterface());
                     } else {
                         if (DBG) logd("stop DHCP client");
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
@@ -1412,9 +1412,10 @@
         logd("Started Dhcp server on " + intf);
    }
 
-    private void stopDhcpServer() {
+    private void stopDhcpServer(String intf) {
         try {
             mNwService.stopTethering();
+            mNwService.clearInterfaceAddresses(intf);
         } catch (Exception e) {
             loge("Error stopping Dhcp server" + e);
             return;