Merge "Permissions to protect bandwidth statistics."
diff --git a/Android.mk b/Android.mk
index d4d9a33..5f3327c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -90,6 +90,7 @@
 	core/java/android/bluetooth/IBluetoothA2dp.aidl \
 	core/java/android/bluetooth/IBluetoothCallback.aidl \
 	core/java/android/bluetooth/IBluetoothHeadset.aidl \
+	core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
 	core/java/android/content/IClipboard.aidl \
 	core/java/android/content/IContentService.aidl \
@@ -244,6 +245,7 @@
 	frameworks/base/core/java/android/app/Notification.aidl \
 	frameworks/base/core/java/android/app/PendingIntent.aidl \
 	frameworks/base/core/java/android/bluetooth/BluetoothDevice.aidl \
+	frameworks/base/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl \
 	frameworks/base/core/java/android/content/ComponentName.aidl \
 	frameworks/base/core/java/android/content/Intent.aidl \
 	frameworks/base/core/java/android/content/IntentSender.aidl \
@@ -364,6 +366,7 @@
     -since ./frameworks/base/api/10.xml 10 \
     -since ./frameworks/base/api/11.xml 11 \
     -since ./frameworks/base/api/12.xml 12 \
+    -since ./frameworks/base/api/13.xml 13 \
 		-werror -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
@@ -414,6 +417,8 @@
 		            resources/samples/NotePad "Note Pad" \
 		-samplecode $(sample_dir)/SampleSyncAdapter \
 		            resources/samples/SampleSyncAdapter "Sample Sync Adapter" \
+		-samplecode $(sample_dir)/RandomMusicPlayer \
+		            resources/samples/RandomMusicPlayer "Random Music Player" \
 		-samplecode $(sample_dir)/RenderScript \
 		            resources/samples/RenderScript "RenderScript" \
 		-samplecode $(sample_dir)/SearchableDictionary \
diff --git a/api/13.xml b/api/13.xml
index 9af0640..2bfa04e 100644
--- a/api/13.xml
+++ b/api/13.xml
@@ -25290,7 +25290,7 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="ActivityGroup"
@@ -30614,6 +30614,17 @@
  visibility="public"
 >
 </method>
+<method name="isDetached"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isHidden"
  return="boolean"
  abstract="false"
@@ -33935,7 +33946,7 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="LocalActivityManager"
@@ -37009,7 +37020,7 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="TabActivity"
@@ -61810,6 +61821,28 @@
  visibility="public"
 >
 </field>
+<field name="FEATURE_SCREEN_LANDSCAPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.hardware.screen.landscape&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEATURE_SCREEN_PORTRAIT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.hardware.screen.portrait&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FEATURE_SENSOR_ACCELEROMETER"
  type="java.lang.String"
  transient="false"
@@ -148973,6 +149006,17 @@
  visibility="public"
 >
 </field>
+<field name="TWEET_TRANSACTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1599362900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <interface name="IBinder.DeathRecipient"
  abstract="true"
diff --git a/api/current.txt b/api/current.txt
index 721e33e..f21a4f3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -190,6 +190,7 @@
     field public static final int accountType = 16843407; // 0x101028f
     field public static final int action = 16842797; // 0x101002d
     field public static final int actionBarSize = 16843499; // 0x10102eb
+    field public static final int actionBarSplitStyle = 16843676; // 0x101039c
     field public static final int actionBarStyle = 16843470; // 0x10102ce
     field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
     field public static final int actionBarTabStyle = 16843507; // 0x10102f3
@@ -601,8 +602,10 @@
     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 = 16843675; // 0x101039b
     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 = 16843674; // 0x101039a
     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
@@ -972,6 +975,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 = 16843677; // 0x101039d
     field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -5893,6 +5897,7 @@
     field public long codeSize;
     field public long dataSize;
     field public long externalCacheSize;
+    field public long externalCodeSize;
     field public long externalDataSize;
     field public long externalMediaSize;
     field public long externalObbSize;
@@ -7417,6 +7422,7 @@
     method public static final android.graphics.Bitmap.CompressFormat[] values();
     enum_constant public static final android.graphics.Bitmap.CompressFormat JPEG;
     enum_constant public static final android.graphics.Bitmap.CompressFormat PNG;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP;
   }
 
   public static final class Bitmap.Config extends java.lang.Enum {
@@ -8364,6 +8370,7 @@
 
   public class SurfaceTexture {
     ctor public SurfaceTexture(int);
+    ctor public SurfaceTexture(int, boolean);
     method public long getTimestamp();
     method public void getTransformMatrix(float[]);
     method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
@@ -9392,6 +9399,7 @@
     method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
     method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo);
     method public void onUpdateSelection(int, int, int, int, int, int);
+    method public void onViewClicked(boolean);
     method public void onWindowHidden();
     method public void onWindowShown();
     method public void requestHideSelf(int);
@@ -9435,6 +9443,7 @@
     method public void updateCursor(android.graphics.Rect);
     method public void updateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(int, int, int, int, int, int);
+    method public void viewClicked(boolean);
   }
 
   public static final class InputMethodService.Insets {
@@ -10433,6 +10442,16 @@
     method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
   }
 
+  public class Metadata {
+    method public boolean getBoolean(int);
+    method public boolean has(int);
+    method public java.util.Set<java.lang.Integer> keySet();
+    field public static final int PAUSE_AVAILABLE = 1; // 0x1
+    field public static final int SEEK_AVAILABLE = 4; // 0x4
+    field public static final int SEEK_BACKWARD_AVAILABLE = 2; // 0x2
+    field public static final int SEEK_FORWARD_AVAILABLE = 3; // 0x3
+  }
+
   public class Ringtone {
     method public int getStreamType();
     method public java.lang.String getTitle(android.content.Context);
@@ -11225,7 +11244,8 @@
     method public static long getUidUdpRxPackets(int);
     method public static long getUidUdpTxBytes(int);
     method public static long getUidUdpTxPackets(int);
-    method public static void setThreadStatsTag(java.lang.String);
+    method public static void setThreadStatsTag(int);
+    method public static deprecated void setThreadStatsTag(java.lang.String);
     method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
     method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
     field public static final int UNSUPPORTED = -1; // 0xffffffff
@@ -11431,11 +11451,14 @@
   }
 
   public class SslError {
-    ctor public SslError(int, android.net.http.SslCertificate);
-    ctor public SslError(int, java.security.cert.X509Certificate);
+    ctor public deprecated SslError(int, android.net.http.SslCertificate);
+    ctor public deprecated SslError(int, java.security.cert.X509Certificate);
+    ctor public SslError(int, android.net.http.SslCertificate, java.lang.String);
+    ctor public SslError(int, java.security.cert.X509Certificate, java.lang.String);
     method public boolean addError(int);
     method public android.net.http.SslCertificate getCertificate();
     method public int getPrimaryError();
+    method public java.lang.String getUrl();
     method public boolean hasError(int);
     field public static final int SSL_EXPIRED = 1; // 0x1
     field public static final int SSL_IDMISMATCH = 2; // 0x2
@@ -15266,11 +15289,11 @@
 
   public final class ContactsContract {
     ctor public ContactsContract();
+    field public static final java.lang.String ALLOW_PROFILE = "allow_profile";
     field public static final java.lang.String AUTHORITY = "com.android.contacts";
     field public static final android.net.Uri AUTHORITY_URI;
     field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
     field public static final java.lang.String DIRECTORY_PARAM_KEY = "directory";
-    field public static final java.lang.String INCLUDE_PROFILE = "include_profile";
     field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
     field public static final java.lang.String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
     field public static final java.lang.String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
@@ -17481,7 +17504,7 @@
 
   public final class KeyChain {
     ctor public KeyChain();
-    method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int);
+    method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
     method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
     method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
   }
@@ -21411,7 +21434,6 @@
     field public static final int AXIS_Y = 1; // 0x1
     field public static final int AXIS_Z = 11; // 0xb
     field public static final int BUTTON_BACK = 8; // 0x8
-    field public static final int BUTTON_ERASER = 32; // 0x20
     field public static final int BUTTON_FORWARD = 16; // 0x10
     field public static final int BUTTON_PRIMARY = 1; // 0x1
     field public static final int BUTTON_SECONDARY = 2; // 0x2
@@ -21635,6 +21657,7 @@
     method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
     method public boolean isAvailable();
     method protected final void onDraw(android.graphics.Canvas);
+    method public void setOpaque(boolean);
     method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
   }
 
@@ -21642,6 +21665,7 @@
     method public abstract void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
     method public abstract void onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
     method public abstract void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+    method public abstract void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
   }
 
   public class TouchDelegate {
@@ -21858,6 +21882,7 @@
     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 isLongClickable();
     method public boolean isOpaque();
@@ -21943,8 +21968,10 @@
     method public void requestLayout();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+    method protected void resetResolvedTextDirection();
     method public static int resolveSize(int, int);
     method public static int resolveSizeAndState(int, int, int);
+    method protected 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);
@@ -21994,6 +22021,7 @@
     method public void setOnDragListener(android.view.View.OnDragListener);
     method public void setOnFocusChangeListener(android.view.View.OnFocusChangeListener);
     method public void setOnGenericMotionListener(android.view.View.OnGenericMotionListener);
+    method public void setOnHoverListener(android.view.View.OnHoverListener);
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
@@ -22042,6 +22070,8 @@
     method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
     method public boolean willNotCacheDrawing();
     method public boolean willNotDraw();
+    field public static android.util.Property ALPHA;
+    field protected static int DEFAULT_TEXT_DIRECTION;
     field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
     field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
     field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
@@ -22831,8 +22861,10 @@
     field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
     field public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
     field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
+    field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
     field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
     field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
+    field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
     field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
     field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20
   }
@@ -22881,6 +22913,7 @@
     method public boolean isFocused();
     method public boolean isLongClickable();
     method public boolean isPassword();
+    method public boolean isScrollable();
     method public boolean isSelected();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain();
@@ -22900,6 +22933,7 @@
     method public void setPackageName(java.lang.CharSequence);
     method public void setParent(android.view.View);
     method public void setPassword(boolean);
+    method public void setScrollable(boolean);
     method public void setSelected(boolean);
     method public void setSource(android.view.View);
     method public void setText(java.lang.CharSequence);
@@ -22921,13 +22955,17 @@
     method public int getItemCount();
     method public android.os.Parcelable getParcelableData();
     method public int getRemovedCount();
+    method public int getScrollX();
+    method public int getScrollY();
     method public android.view.accessibility.AccessibilityNodeInfo getSource();
     method public java.util.List<java.lang.CharSequence> getText();
+    method public int getToIndex();
     method public int getWindowId();
     method public boolean isChecked();
     method public boolean isEnabled();
     method public boolean isFullScreen();
     method public boolean isPassword();
+    method public boolean isScrollable();
     method public static android.view.accessibility.AccessibilityRecord obtain(android.view.accessibility.AccessibilityRecord);
     method public static android.view.accessibility.AccessibilityRecord obtain();
     method public void recycle();
@@ -22944,7 +22982,11 @@
     method public void setParcelableData(android.os.Parcelable);
     method public void setPassword(boolean);
     method public void setRemovedCount(int);
+    method public void setScrollX(int);
+    method public void setScrollY(int);
+    method public void setScrollable(boolean);
     method public void setSource(android.view.View);
+    method public void setToIndex(int);
   }
 
 }
@@ -23477,6 +23519,7 @@
     method public void updateCursor(android.view.View, int, int, int, int);
     method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(android.view.View, int, int, int, int);
+    method public void viewClicked(android.view.View);
     field public static final int HIDE_IMPLICIT_ONLY = 1; // 0x1
     field public static final int HIDE_NOT_ALWAYS = 2; // 0x2
     field public static final int RESULT_HIDDEN = 3; // 0x3
@@ -23497,6 +23540,7 @@
     method public abstract void updateCursor(android.graphics.Rect);
     method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public abstract void updateSelection(int, int, int, int, int, int);
+    method public abstract void viewClicked(boolean);
   }
 
   public static abstract interface InputMethodSession.EventCallback {
@@ -24876,9 +24920,6 @@
   }
 
   public static abstract class GridLayout.Alignment {
-    ctor public GridLayout.Alignment();
-    method public abstract int getAlignmentValue(android.view.View, int, int);
-    method public int getSizeInCell(android.view.View, int, int, int);
   }
 
   public static class GridLayout.Group {
@@ -27049,9 +27090,7 @@
 
   public final class FilePermission extends java.security.Permission implements java.io.Serializable {
     ctor public FilePermission(java.lang.String, java.lang.String);
-    method public boolean equals(java.lang.Object);
     method public java.lang.String getActions();
-    method public int hashCode();
     method public boolean implies(java.security.Permission);
   }
 
@@ -29810,8 +29849,8 @@
     ctor public DatagramSocket(java.net.SocketAddress) throws java.net.SocketException;
     method public void bind(java.net.SocketAddress) throws java.net.SocketException;
     method public void close();
-    method public void connect(java.net.InetAddress, int);
     method public void connect(java.net.SocketAddress) throws java.net.SocketException;
+    method public void connect(java.net.InetAddress, int);
     method public void disconnect();
     method public boolean getBroadcast() throws java.net.SocketException;
     method public java.nio.channels.DatagramChannel getChannel();
@@ -30299,9 +30338,7 @@
 
   public final class SocketPermission extends java.security.Permission implements java.io.Serializable {
     ctor public SocketPermission(java.lang.String, java.lang.String);
-    method public boolean equals(java.lang.Object);
     method public java.lang.String getActions();
-    method public int hashCode();
     method public boolean implies(java.security.Permission);
   }
 
@@ -31308,9 +31345,7 @@
   public final class AllPermission extends java.security.Permission {
     ctor public AllPermission(java.lang.String, java.lang.String);
     ctor public AllPermission();
-    method public boolean equals(java.lang.Object);
     method public java.lang.String getActions();
-    method public int hashCode();
     method public boolean implies(java.security.Permission);
   }
 
@@ -31324,9 +31359,7 @@
   public abstract class BasicPermission extends java.security.Permission implements java.io.Serializable {
     ctor public BasicPermission(java.lang.String);
     ctor public BasicPermission(java.lang.String, java.lang.String);
-    method public boolean equals(java.lang.Object);
     method public java.lang.String getActions();
-    method public int hashCode();
     method public boolean implies(java.security.Permission);
   }
 
@@ -31689,10 +31722,8 @@
   public abstract class Permission implements java.security.Guard java.io.Serializable {
     ctor public Permission(java.lang.String);
     method public void checkGuard(java.lang.Object) throws java.lang.SecurityException;
-    method public abstract boolean equals(java.lang.Object);
     method public abstract java.lang.String getActions();
     method public final java.lang.String getName();
-    method public abstract int hashCode();
     method public abstract boolean implies(java.security.Permission);
     method public java.security.PermissionCollection newPermissionCollection();
   }
@@ -31949,13 +31980,11 @@
 
   public final class UnresolvedPermission extends java.security.Permission implements java.io.Serializable {
     ctor public UnresolvedPermission(java.lang.String, java.lang.String, java.lang.String, java.security.cert.Certificate[]);
-    method public boolean equals(java.lang.Object);
     method public java.lang.String getActions();
     method public java.lang.String getUnresolvedActions();
     method public java.security.cert.Certificate[] getUnresolvedCerts();
     method public java.lang.String getUnresolvedName();
     method public java.lang.String getUnresolvedType();
-    method public int hashCode();
     method public boolean implies(java.security.Permission);
   }
 
@@ -39471,11 +39500,9 @@
 
   public final class PrivateCredentialPermission extends java.security.Permission {
     ctor public PrivateCredentialPermission(java.lang.String, java.lang.String);
-    method public boolean equals(java.lang.Object);
     method public java.lang.String getActions();
     method public java.lang.String getCredentialClass();
     method public java.lang.String[][] getPrincipals();
-    method public int hashCode();
     method public boolean implies(java.security.Permission);
   }
 
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
index 788b686..16e0505 100644
--- a/build/phone-hdpi-512-dalvik-heap.mk
+++ b/build/phone-hdpi-512-dalvik-heap.mk
@@ -19,5 +19,5 @@
 
 PRODUCT_PROPERTY_OVERRIDES += \
     dalvik.vm.heapstartsize=5m \
-    dalvik.vm.heapgrowthlimit=32m \
+    dalvik.vm.heapgrowthlimit=48m \
     dalvik.vm.heapsize=128m
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 424b70a..479b70a 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -33,6 +33,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.util.AndroidException;
 import android.view.IWindowManager;
 
@@ -199,6 +200,10 @@
                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
             } else if (opt.equals("--grant-write-uri-permission")) {
                 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            } else if (opt.equals("--exclude-stopped-packages")) {
+                intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
+            } else if (opt.equals("--include-stopped-packages")) {
+                intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
             } else if (opt.equals("--debug-log-resolution")) {
                 intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
             } else if (opt.equals("--activity-brought-to-front")) {
@@ -227,6 +232,10 @@
                 intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             } else if (opt.equals("--activity-single-top")) {
                 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+            } else if (opt.equals("--activity-clear-task")) {
+                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            } else if (opt.equals("--activity-task-on-home")) {
+                intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
             } else if (opt.equals("--receiver-registered-only")) {
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             } else if (opt.equals("--receiver-replace-pending")) {
@@ -400,7 +409,8 @@
                 argKey = nextArgRequired();
                 argValue = nextArgRequired();
                 args.putString(argKey, argValue);
-            } else if (opt.equals("--no_window_animation")) {
+            } else if (opt.equals("--no_window_animation")
+                    || opt.equals("--no-window-animation")) {
                 no_window_animation = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
@@ -440,15 +450,43 @@
         }
     }
 
+    static void removeWallOption() {
+        String props = SystemProperties.get("dalvik.vm.extra-opts");
+        if (props != null && props.contains("-Xprofile:wallclock")) {
+            props = props.replace("-Xprofile:wallclock", "");
+            props = props.trim();
+            SystemProperties.set("dalvik.vm.extra-opts", props);
+        }
+    }
+    
     private void runProfile() throws Exception {
         String profileFile = null;
         boolean start = false;
-        String process = nextArgRequired();
-        ParcelFileDescriptor fd = null;
-
+        boolean wall = false;
+        
+        String process = null;
+        
         String cmd = nextArgRequired();
         if ("start".equals(cmd)) {
             start = true;
+            wall = "--wall".equals(nextOption());
+            process = nextArgRequired();
+        } else if ("stop".equals(cmd)) {
+            process = nextArgRequired();
+        } else {
+            // Compatibility with old syntax: process is specified first.
+            process = cmd;
+            cmd = nextArgRequired();
+            if ("start".equals(cmd)) {
+                start = true;
+            } else if (!"stop".equals(cmd)) {
+                throw new IllegalArgumentException("Profile command " + process + " not valid");
+            }
+        }
+        
+        ParcelFileDescriptor fd = null;
+
+        if (start) {
             profileFile = nextArgRequired();
             try {
                 fd = ParcelFileDescriptor.open(
@@ -460,12 +498,27 @@
                 System.err.println("Error: Unable to open file: " + profileFile);
                 return;
             }
-        } else if (!"stop".equals(cmd)) {
-            throw new IllegalArgumentException("Profile command " + cmd + " not valid");
         }
 
-        if (!mAm.profileControl(process, start, profileFile, fd)) {
-            throw new AndroidException("PROFILE FAILED on process " + process);
+        try {
+            if (wall) {
+                // XXX doesn't work -- this needs to be set before booting.
+                String props = SystemProperties.get("dalvik.vm.extra-opts");
+                if (props == null || !props.contains("-Xprofile:wallclock")) {
+                    props = props + " -Xprofile:wallclock";
+                    //SystemProperties.set("dalvik.vm.extra-opts", props);
+                }
+            } else if (start) {
+                //removeWallOption();
+            }
+            if (!mAm.profileControl(process, start, profileFile, fd)) {
+                wall = false;
+                throw new AndroidException("PROFILE FAILED on process " + process);
+            }
+        } finally {
+            if (!wall) {
+                //removeWallOption();
+            }
         }
     }
 
@@ -1012,62 +1065,76 @@
     private static void showUsage() {
         System.err.println(
                 "usage: am [subcommand] [options]\n" +
+                "usage: am start [-D] [-W] <INTENT>\n" +
+                "       am startservice <INTENT>\n" +
+                "       am force-stop <PACKAGE>\n" +
+                "       am broadcast <INTENT>\n" +
+                "       am instrument [-r] [-e <NAME> <VALUE>] [-p] [-w]\n" +
+                "               [--no-window-animation] <COMPONENT>\n" +
+                "       am profile start <PROCESS> <FILE>\n" +
+                "       am profile stop <PROCESS>\n" +
+                "       am dumpheap [flags] <PROCESS> <FILE>\n" +
+                "       am monitor [--gdb <port>]\n" +
+                "       am screen-compat [on|off] <PACKAGE>\n" +
+                "       am display-size [reset|MxN]\n" +
                 "\n" +
-                "    start an Activity: am start [-D] [-W] <INTENT>\n" +
-                "        -D: enable debugging\n" +
-                "        -W: wait for launch to complete\n" +
+                "am start: start an Activity.  Options are:\n" +
+                "    -D: enable debugging\n" +
+                "    -W: wait for launch to complete\n" +
                 "\n" +
-                "    start a Service: am startservice <INTENT>\n" +
+                "am startservice: start a Service.\n" +
                 "\n" +
-                "    force stop everything associated with a package: force-stop <package>\n" +
+                "am force-stop: force stop everything associated with <PACKAGE>.\n" +
                 "\n" +
-                "    send a broadcast Intent: am broadcast <INTENT>\n" +
+                "am broadcast: send a broadcast Intent.\n" +
                 "\n" +
-                "    start an Instrumentation: am instrument [flags] <COMPONENT>\n" +
-                "        -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)\n" +
-                "        -e <NAME> <VALUE>: set argument <NAME> to <VALUE>\n" +
-                "        -p <FILE>: write profiling data to <FILE>\n" +
-                "        -w: wait for instrumentation to finish before returning\n" +
+                "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
+                "  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:\n" +
+                "    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with\n" +
+                "        [-e perf true] to generate raw output for performance measurements.\n" +
+                "    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a\n" +
+                "        common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
+                "    -p <FILE>: write profiling data to <FILE>\n" +
+                "    -w: wait for instrumentation to finish before returning.  Required for\n" +
+                "        test runners.\n" +
+                "    --no-window-animation: turn off window animations will running.\n" +
                 "\n" +
-                "    run a test package against an application: am instrument [flags] <TEST_PACKAGE>/<RUNNER_CLASS>\n" +
-                "        -e <testrunner_flag> <testrunner_value> [,<testrunner_value>]\n" +
-                "        -w wait for the test to finish (required)\n" +
-                "        -r use with -e perf true to generate raw output for performance measurements\n" +
+                "am profile: start and stop profiler on a process.\n" +
                 "\n" +
-                "    start profiling: am profile <PROCESS> start <FILE>\n" +
-                "    stop profiling: am profile <PROCESS> stop\n" +
-                "    dump heap: am dumpheap [flags] <PROCESS> <FILE>\n" +
-                "        -n: dump native heap instead of managed heap\n" +
+                "am dumpheap: dump the heap of a process.  Options are:\n" +
+                "    -n: dump native heap instead of managed heap\n" +
                 "\n" +
-                "    start monitoring: am monitor [--gdb <port>]\n" +
-                "        --gdb: start gdbserv on the given port at crash/ANR\n" +
+                "am monitor: start monitoring for crashes or ANRs.\n" +
+                "    --gdb: start gdbserv on the given port at crash/ANR\n" +
                 "\n" +
-                "    control screen compatibility: am screen-compat [on|off] [package]\n" +
+                "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
                 "\n" +
-                "    override display size: am display-size [reset|MxN]\n" +
+                "am display-size: override display size.\n" +
                 "\n" +
-                "    <INTENT> specifications include these flags:\n" +
-                "        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
-                "        [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
-                "        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
-                "        [--esn <EXTRA_KEY> ...]\n" +
-                "        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
-                "        [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
-                "        [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
-                "        [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
-                "        [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
-                "        [-n <COMPONENT>] [-f <FLAGS>]\n" +
-                "        [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
-                "        [--debug-log-resolution]\n" +
-                "        [--activity-brought-to-front] [--activity-clear-top]\n" +
-                "        [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
-                "        [--activity-launched-from-history] [--activity-multiple-task]\n" +
-                "        [--activity-no-animation] [--activity-no-history]\n" +
-                "        [--activity-no-user-action] [--activity-previous-is-top]\n" +
-                "        [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
-                "        [--activity-single-top]\n" +
-                "        [--receiver-registered-only] [--receiver-replace-pending]\n" +
-                "        [<URI>]\n"
+                "<INTENT> specifications include these flags and arguments:\n" +
+                "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+                "    [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+                "    [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+                "    [--esn <EXTRA_KEY> ...]\n" +
+                "    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+                "    [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+                "    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+                "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+                "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
+                "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
+                "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
+                "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
+                "    [--include-stopped-packages]\n" +
+                "    [--activity-brought-to-front] [--activity-clear-top]\n" +
+                "    [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
+                "    [--activity-launched-from-history] [--activity-multiple-task]\n" +
+                "    [--activity-no-animation] [--activity-no-history]\n" +
+                "    [--activity-no-user-action] [--activity-previous-is-top]\n" +
+                "    [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
+                "    [--activity-single-top] [--activity-clear-task]\n" +
+                "    [--activity-task-on-home]\n" +
+                "    [--receiver-registered-only] [--receiver-replace-pending]\n" +
+                "    [<URI>]\n"
                 );
     }
 }
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 0acba8b..ccd668d 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -213,9 +213,10 @@
     // create the native surface
     sp<SurfaceControl> control = session()->createSurface(
             0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
-    session()->openTransaction();
+
+    SurfaceComposerClient::openGlobalTransaction();
     control->setLayer(0x40000000);
-    session()->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     sp<Surface> s = control->getSurface();
 
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index d45ac192..26b9113 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -288,8 +288,9 @@
 }
 
 int get_size(const char *pkgname, const char *apkpath,
-             const char *fwdlock_apkpath,
-             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize)
+             const char *fwdlock_apkpath, const char *asecpath,
+             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
+             int64_t* _asecsize)
 {
     DIR *d;
     int dfd;
@@ -300,6 +301,7 @@
     int64_t codesize = 0;
     int64_t datasize = 0;
     int64_t cachesize = 0;
+    int64_t asecsize = 0;
 
         /* count the source apk as code -- but only if it's not
          * on the /system partition and its not on the sdcard.
@@ -324,6 +326,14 @@
         }
     }
 
+        /* compute asec size if it is given
+         */
+    if (asecpath != NULL && asecpath[0] != '!') {
+        if (stat(asecpath, &s) == 0) {
+            asecsize += stat_size(&s);
+        }
+    }
+
     if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
         goto done;
     }
@@ -370,6 +380,7 @@
     *_codesize = codesize;
     *_datasize = datasize;
     *_cachesize = cachesize;
+    *_asecsize = asecsize;
     return 0;
 }
 
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index c062d36..feb6b92 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -77,16 +77,18 @@
     int64_t codesize = 0;
     int64_t datasize = 0;
     int64_t cachesize = 0;
+    int64_t asecsize = 0;
     int res = 0;
 
         /* pkgdir, apkpath */
-    res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize);
+    res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
      * doesn't go over REPLY_MAX in the future.
      */
-    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64, codesize, datasize, cachesize);
+    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
+            codesize, datasize, cachesize, asecsize);
     return res;
 }
 
@@ -137,7 +139,7 @@
     { "freecache",            1, do_free_cache },
     { "rmcache",              1, do_rm_cache },
     { "protect",              2, do_protect },
-    { "getsize",              3, do_get_size },
+    { "getsize",              4, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index e5f6739..c5872b8 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -143,7 +143,8 @@
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
 int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
-             int64_t *codesize, int64_t *datasize, int64_t *cachesize);
+             const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+             int64_t *asecsize);
 int free_cache(int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index b48be6ef..1c1f37a 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -363,6 +363,7 @@
                 response = writeMasterKey(pw);
             }
             if (response == NO_ERROR) {
+                memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
                 setupMasterKeys();
             }
             return response;
@@ -707,7 +708,7 @@
     uid_t euid;
     uint32_t perms;
 } users[] = {
-    {AID_SYSTEM,   ~0,         ~GET},
+    {AID_SYSTEM,   ~0,         ~0},
     {AID_VPN,      AID_SYSTEM, GET},
     {AID_WIFI,     AID_SYSTEM, GET},
     {AID_ROOT,     AID_SYSTEM, GET},
diff --git a/cmds/keystore/test-keystore b/cmds/keystore/test-keystore
new file mode 100755
index 0000000..3be51b3
--- /dev/null
+++ b/cmds/keystore/test-keystore
@@ -0,0 +1,273 @@
+#!/bin/bash
+#
+# 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.
+
+set -e
+
+prefix=$0
+log_file=$prefix.log
+baseline_file=$prefix.baseline
+
+function cleanup_output() {
+    rm -f $log_file
+    rm -f $baseline_file
+}
+
+function log() {
+    echo "$@"
+    append $log_file \# "$@"
+    append $baseline_file \# "$@"
+}
+
+function expect() {
+    append $baseline_file "$@"
+}
+
+function append() {
+    declare -r file=$1
+    shift
+    echo "$@" >> $file
+}
+
+function run() {
+    # strip out carriage returns from adb
+    # strip out date/time from ls -l
+    "$@" | tr --delete '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
+}
+
+function keystore() {
+    declare -r user=$1
+    shift
+    run adb shell su $user keystore_cli "$@"
+}
+
+function list_keystore_directory() {
+    run adb shell ls -al /data/misc/keystore
+}
+
+function compare() {
+    log "comparing $baseline_file and $log_file"
+    diff $baseline_file $log_file || (log $tag FAILED && exit 1)
+}
+
+function test_basic() {
+
+    #
+    # reset
+    #
+    log "reset keystore as system user"
+    keystore system r
+    expect "1 No error"
+    list_keystore_directory
+
+    #
+    # basic tests as system/root
+    #
+    log "root does not have permission to run test"
+    keystore root t
+    expect "6 Permission denied"
+    
+    log "but system user does"
+    keystore system t
+    expect "3 Uninitialized"
+    list_keystore_directory
+
+    log "password is now bar"
+    keystore system p bar
+    expect "1 No error"
+    list_keystore_directory
+    expect "-rw------- keystore keystore       84 .masterkey"
+    
+    log "no error implies initialized and unlocked"
+    keystore system t
+    expect "1 No error"
+    
+    log "saw with no argument"
+    keystore system s
+    expect "5 Protocol error"
+
+    log "saw nothing"
+    keystore system s ""
+    expect "1 No error"
+
+    log "add key baz"
+    keystore system i baz quux
+    expect "1 No error"
+
+    log "1000 is uid of system"
+    list_keystore_directory
+    expect "-rw------- keystore keystore       84 .masterkey"
+    expect "-rw------- keystore keystore       52 1000_baz"
+
+    log "saw baz"
+    keystore system s ""
+    expect "1 No error"
+    expect "baz"
+
+    log "get baz"
+    keystore system g baz
+    expect "1 No error"
+    expect "quux"
+
+    log "root can read system user keys (as can wifi or vpn users)"
+    keystore root g baz
+    expect "1 No error"
+    expect "quux"
+
+    #
+    # app user tests
+    #
+
+    # app_0 has uid 10000, as seen below
+    log "other uses cannot see the system keys"
+    keystore app_0 g baz
+    expect "7 Key not found"
+    
+    log "app user cannot use reset, password, lock, unlock"
+    keystore app_0 r
+    expect "6 Permission denied"
+    keystore app_0 p
+    expect "6 Permission denied"
+    keystore app_0 l
+    expect "6 Permission denied"
+    keystore app_0 u
+    expect "6 Permission denied"
+
+    log "install app_0 key"
+    keystore app_0 i 0x deadbeef
+    expect 1 No error
+    list_keystore_directory
+    expect "-rw------- keystore keystore       84 .masterkey"
+    expect "-rw------- keystore keystore       52 10000_0x"
+    expect "-rw------- keystore keystore       52 1000_baz"
+
+    log "get with no argument"
+    keystore app_0 g
+    expect "5 Protocol error"
+    
+    keystore app_0 g 0x
+    expect "1 No error"
+    expect "deadbeef"
+    
+    keystore app_0 i fred barney
+    expect "1 No error"
+    
+    keystore app_0 s ""
+    expect "1 No error"
+    expect "0x"
+    expect "fred"
+
+    log "note that saw returns the suffix of prefix matches"
+    keystore app_0 s fr # fred
+    expect "1 No error"
+    expect "ed" # fred
+
+    #
+    # lock tests
+    #
+    log "lock the store as system"
+    keystore system l
+    expect "1 No error"
+    keystore system t
+    expect "2 Locked"
+    
+    log "saw works while locked"
+    keystore app_0 s ""
+    expect "1 No error"
+    expect "0x"
+    expect "fred"
+
+    log "...but cannot read keys..."
+    keystore app_0 g 0x
+    expect "2 Locked"
+    
+    log "...but they can be deleted."
+    keystore app_0 e 0x
+    expect "1 No error"
+    keystore app_0 d 0x
+    expect "1 No error"
+    keystore app_0 e 0x
+    expect "7 Key not found"
+
+    #
+    # password
+    #
+    log "wrong password"
+    keystore system u foo
+    expect "13 Wrong password (4 tries left)"
+    log "right password"
+    keystore system u bar
+    expect "1 No error"
+    
+    log "make the password foo"
+    keystore system p foo
+    expect "1 No error"
+    
+    #
+    # final reset
+    #
+    log "reset wipes everything for all users"
+    keystore system r
+    expect "1 No error"
+    list_keystore_directory
+    
+    keystore system t
+    expect "3 Uninitialized"
+
+}
+
+function test_4599735() {
+    # http://b/4599735
+    log "start regression test for b/4599735"
+    keystore system r
+    expect "1 No error"
+
+    keystore system p foo
+    expect "1 No error"
+
+    keystore system i baz quux
+    expect "1 No error"
+    
+    keystore root g baz
+    expect "1 No error"
+    expect "quux"
+
+    keystore system l
+    expect "1 No error"
+
+    keystore system p foo
+    expect "1 No error"
+
+    log "after unlock, regression led to result of '8 Value corrupted'"
+    keystore root g baz
+    expect "1 No error"
+    expect "quux"
+
+    keystore system r
+    expect "1 No error"
+    log "end regression test for b/4599735"
+}
+
+function main() {
+    cleanup_output
+    log $tag START
+    test_basic
+    test_4599735
+    compare
+    log $tag PASSED
+    cleanup_output
+}
+
+main
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index e433079..c980715 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -125,12 +125,12 @@
             return;
         }
 
-        if ("setInstallLocation".equals(op)) {
+        if ("set-install-location".equals(op)) {
             runSetInstallLocation();
             return;
         }
 
-        if ("getInstallLocation".equals(op)) {
+        if ("get-install-location".equals(op)) {
             runGetInstallLocation();
             return;
         }
@@ -1094,8 +1094,7 @@
     }
 
     private static void showUsage() {
-        System.err.println("usage: pm [list|path|install|uninstall]");
-        System.err.println("       pm list packages [-f] [-d] [-e] [-s] [-e] [-u] [FILTER]");
+        System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-e] [-u] [FILTER]");
         System.err.println("       pm list permission-groups");
         System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
         System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
@@ -1107,66 +1106,66 @@
         System.err.println("       pm clear PACKAGE");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable PACKAGE_OR_COMPONENT");
-        System.err.println("       pm setInstallLocation [0/auto] [1/internal] [2/external]");
+        System.err.println("       pm disable-user PACKAGE_OR_COMPONENT");
+        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
+        System.err.println("       pm get-install-location");
         System.err.println("       pm createUser USER_NAME");
         System.err.println("       pm removeUser USER_ID");
         System.err.println("");
-        System.err.println("The list packages command prints all packages, optionally only");
-        System.err.println("those whose package name contains the text in FILTER.  Options:");
-        System.err.println("  -f: see their associated file.");
-        System.err.println("  -d: filter to only show disbled packages.");
-        System.err.println("  -e: filter to only show enabled packages.");
-        System.err.println("  -s: filter to only show system packages.");
-        System.err.println("  -3: filter to only show third party packages.");
-        System.err.println("  -u: also include uninstalled packages.");
+        System.err.println("pm list packages: prints all packages, optionally only");
+        System.err.println("  those whose package name contains the text in FILTER.  Options:");
+        System.err.println("    -f: see their associated file.");
+        System.err.println("    -d: filter to only show disbled packages.");
+        System.err.println("    -e: filter to only show enabled packages.");
+        System.err.println("    -s: filter to only show system packages.");
+        System.err.println("    -3: filter to only show third party packages.");
+        System.err.println("    -u: also include uninstalled packages.");
         System.err.println("");
-        System.err.println("The list permission-groups command prints all known");
-        System.err.println("permission groups.");
+        System.err.println("pm list permission-groups: prints all known permission groups.");
         System.err.println("");
-        System.err.println("The list permissions command prints all known");
-        System.err.println("permissions, optionally only those in GROUP.  Options:");
-        System.err.println("  -g: organize by group.");
-        System.err.println("  -f: print all information.");
-        System.err.println("  -s: short summary.");
-        System.err.println("  -d: only list dangerous permissions.");
-        System.err.println("  -u: list only the permissions users will see.");
+        System.err.println("pm list permissions: prints all known permissions, optionally only");
+        System.err.println("  those in GROUP.  Options:");
+        System.err.println("    -g: organize by group.");
+        System.err.println("    -f: print all information.");
+        System.err.println("    -s: short summary.");
+        System.err.println("    -d: only list dangerous permissions.");
+        System.err.println("    -u: list only the permissions users will see.");
         System.err.println("");
-        System.err.println("The list instrumentation command prints all instrumentations,");
-        System.err.println("or only those that target a specified package.  Options:");
-        System.err.println("  -f: see their associated file.");
-        System.err.println("(Use this command to list all test packages, or use <TARGET-PACKAGE> ");
-        System.err.println(" to list the test packages for a particular application. The -f ");
-        System.err.println(" option lists the .apk file for the test package.)");
+        System.err.println("pm list instrumentation: use to list all test packages; optionally");
+        System.err.println("  supply <TARGET-PACKAGE> to list the test packages for a particular");
+        System.err.println("  application.  Options:");
+        System.err.println("    -f: list the .apk file for the test package.");
         System.err.println("");
-        System.err.println("The list features command prints all features of the system.");
+        System.err.println("pm list features: prints all features of the system.");
         System.err.println("");
-        System.err.println("The path command prints the path to the .apk of a package.");
+        System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
         System.err.println("");
-        System.err.println("The install command installs a package to the system.  Options:");
-        System.err.println("  -l: install the package with FORWARD_LOCK.");
-        System.err.println("  -r: reinstall an exisiting app, keeping its data.");
-        System.err.println("  -t: allow test .apks to be installed.");
-        System.err.println("  -i: specify the installer package name.");
-        System.err.println("  -s: install package on sdcard.");
-        System.err.println("  -f: install package on internal flash.");
+        System.err.println("pm install: installs a package to the system.  Options:");
+        System.err.println("    -l: install the package with FORWARD_LOCK.");
+        System.err.println("    -r: reinstall an exisiting app, keeping its data.");
+        System.err.println("    -t: allow test .apks to be installed.");
+        System.err.println("    -i: specify the installer package name.");
+        System.err.println("    -s: install package on sdcard.");
+        System.err.println("    -f: install package on internal flash.");
         System.err.println("");
-        System.err.println("The uninstall command removes a package from the system. Options:");
-        System.err.println("  -k: keep the data and cache directories around.");
-        System.err.println("after the package removal.");
+        System.err.println("pm uninstall: removes a package from the system. Options:");
+        System.err.println("    -k: keep the data and cache directories around after package removal.");
         System.err.println("");
-        System.err.println("The clear command deletes all data associated with a package.");
+        System.err.println("pm clear: deletes all data associated with a package.");
         System.err.println("");
-        System.err.println("The enable and disable commands change the enabled state of");
-        System.err.println("a given package or component (written as \"package/class\").");
+        System.err.println("pm enable, disable, disable-user: these commands change the enabled state");
+        System.err.println("  of a given package or component (written as \"package/class\").");
         System.err.println("");
-        System.err.println("The getInstallLocation command gets the current install location");
-        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("pm get-install-location: returns the current install location.");
+        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("The setInstallLocation command changes the default install location");
-        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("pm set-install-location: changes the default install location.");
+        System.err.println("  NOTE: this is only intended for debugging; using this can cause");
+        System.err.println("  applications to break and other undersireable behavior.");
+        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");
     }
 }
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 289665f..6fa66cf 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/NativeWindowWrapper.h>
 #include <media/stagefright/Utils.h>
 
 #include <surfaceflinger/ISurfaceComposer.h>
@@ -39,10 +40,12 @@
 using namespace android;
 
 struct Controller : public AHandler {
-    Controller(const char *uri, bool decodeAudio, const sp<Surface> &surface)
+    Controller(const char *uri, bool decodeAudio,
+               const sp<Surface> &surface, bool renderToSurface)
         : mURI(uri),
           mDecodeAudio(decodeAudio),
           mSurface(surface),
+          mRenderToSurface(renderToSurface),
           mCodec(new ACodec) {
         CHECK(!mDecodeAudio || mSurface == NULL);
     }
@@ -97,7 +100,8 @@
                 sp<AMessage> format = makeFormat(mSource->getFormat());
 
                 if (mSurface != NULL) {
-                    format->setObject("surface", mSurface);
+                    format->setObject(
+                            "native-window", new NativeWindowWrapper(mSurface));
                 }
 
                 mCodec->initiateSetup(format);
@@ -220,6 +224,7 @@
     AString mURI;
     bool mDecodeAudio;
     sp<Surface> mSurface;
+    bool mRenderToSurface;
     sp<ACodec> mCodec;
     sp<MediaSource> mSource;
 
@@ -451,7 +456,7 @@
                 inBuffer->release();
                 inBuffer = NULL;
 
-                // break;  // Don't coalesce
+                break;  // Don't coalesce
             }
 
             LOGV("coalesced %d input buffers", n);
@@ -479,6 +484,10 @@
         sp<AMessage> reply;
         CHECK(msg->findMessage("reply", &reply));
 
+        if (mRenderToSurface) {
+            reply->setInt32("render", 1);
+        }
+
         reply->post();
     }
 
@@ -491,7 +500,8 @@
     fprintf(stderr, "       -a(udio)\n");
 
     fprintf(stderr,
-            "       -s(surface) Allocate output buffers on a surface.\n");
+            "       -S(urface) Allocate output buffers on a surface.\n"
+            "       -R(ender)  Render surface-allocated buffers.\n");
 }
 
 int main(int argc, char **argv) {
@@ -499,18 +509,23 @@
 
     bool decodeAudio = false;
     bool useSurface = false;
+    bool renderToSurface = false;
 
     int res;
-    while ((res = getopt(argc, argv, "has")) >= 0) {
+    while ((res = getopt(argc, argv, "haSR")) >= 0) {
         switch (res) {
             case 'a':
                 decodeAudio = true;
                 break;
 
-            case 's':
+            case 'S':
                 useSurface = true;
                 break;
 
+            case 'R':
+                renderToSurface = true;
+                break;
+
             case '?':
             case 'h':
             default:
@@ -553,16 +568,18 @@
         CHECK(control != NULL);
         CHECK(control->isValid());
 
-        CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
+        SurfaceComposerClient::openGlobalTransaction();
         CHECK_EQ(control->setLayer(30000), (status_t)OK);
         CHECK_EQ(control->show(), (status_t)OK);
-        CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+        SurfaceComposerClient::closeGlobalTransaction();
 
         surface = control->getSurface();
         CHECK(surface != NULL);
     }
 
-    sp<Controller> controller = new Controller(argv[0], decodeAudio, surface);
+    sp<Controller> controller =
+        new Controller(argv[0], decodeAudio, surface, renderToSurface);
+
     looper->registerHandler(controller);
 
     controller->startAsync();
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index ca77185..1a5b7f3 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -74,8 +74,6 @@
 
 static sp<ANativeWindow> gSurface;
 
-#define USE_SURFACE_COMPOSER 0
-
 static int64_t getNowUs() {
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -388,13 +386,15 @@
 
     sp<MediaSource> mSource;
     StreamType mStreamType;
+    bool mSawFirstIDRFrame;
 
     DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
 };
 
 DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
     : mSource(source),
-      mStreamType(OTHER) {
+      mStreamType(OTHER),
+      mSawFirstIDRFrame(false) {
     const char *mime;
     CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
 
@@ -410,6 +410,8 @@
 }
 
 status_t DetectSyncSource::start(MetaData *params) {
+    mSawFirstIDRFrame = false;
+
     return mSource->start(params);
 }
 
@@ -439,16 +441,30 @@
 
 status_t DetectSyncSource::read(
         MediaBuffer **buffer, const ReadOptions *options) {
-    status_t err = mSource->read(buffer, options);
+    for (;;) {
+        status_t err = mSource->read(buffer, options);
 
-    if (err != OK) {
-        return err;
-    }
+        if (err != OK) {
+            return err;
+        }
 
-    if (mStreamType == AVC && isIDRFrame(*buffer)) {
-        (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
-    } else {
-        (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
+        if (mStreamType == AVC) {
+            bool isIDR = isIDRFrame(*buffer);
+            (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, isIDR);
+            if (isIDR) {
+                mSawFirstIDRFrame = true;
+            }
+        } else {
+            (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
+        }
+
+        if (mStreamType != AVC || mSawFirstIDRFrame) {
+            break;
+        }
+
+        // Ignore everything up to the first IDR frame.
+        (*buffer)->release();
+        *buffer = NULL;
     }
 
     return OK;
@@ -561,6 +577,7 @@
     fprintf(stderr, "       -x display a histogram of decoding times/fps "
                     "(video only)\n");
     fprintf(stderr, "       -S allocate buffers from a surface\n");
+    fprintf(stderr, "       -T allocate buffers from a surface texture\n");
 }
 
 int main(int argc, char **argv) {
@@ -572,6 +589,7 @@
     bool extractThumbnail = false;
     bool seekTest = false;
     bool useSurfaceAlloc = false;
+    bool useSurfaceTexAlloc = false;
     gNumRepetitions = 1;
     gMaxNumFrames = 0;
     gReproduceBug = -1;
@@ -586,7 +604,7 @@
     sp<LiveSession> liveSession;
 
     int res;
-    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxS")) >= 0) {
+    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxST")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -677,6 +695,12 @@
                 break;
             }
 
+            case 'T':
+            {
+                useSurfaceTexAlloc = true;
+                break;
+            }
+
             case '?':
             case 'h':
             default:
@@ -825,34 +849,35 @@
     sp<SurfaceComposerClient> composerClient;
     sp<SurfaceControl> control;
 
-    if (useSurfaceAlloc && !audioOnly) {
-#if USE_SURFACE_COMPOSER
-        composerClient = new SurfaceComposerClient;
-        CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
+        if (useSurfaceAlloc) {
+            composerClient = new SurfaceComposerClient;
+            CHECK_EQ(composerClient->initCheck(), (status_t)OK);
 
-        control = composerClient->createSurface(
-                getpid(),
-                String8("A Surface"),
-                0,
-                1280,
-                800,
-                PIXEL_FORMAT_RGB_565,
-                0);
+            control = composerClient->createSurface(
+                    String8("A Surface"),
+                    0,
+                    1280,
+                    800,
+                    PIXEL_FORMAT_RGB_565,
+                    0);
 
-        CHECK(control != NULL);
-        CHECK(control->isValid());
+            CHECK(control != NULL);
+            CHECK(control->isValid());
 
-        CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
-        CHECK_EQ(control->setLayer(30000), (status_t)OK);
-        CHECK_EQ(control->show(), (status_t)OK);
-        CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+            SurfaceComposerClient::openGlobalTransaction();
+            CHECK_EQ(control->setLayer(30000), (status_t)OK);
+            CHECK_EQ(control->show(), (status_t)OK);
+            SurfaceComposerClient::closeGlobalTransaction();
 
-        gSurface = control->getSurface();
-        CHECK(gSurface != NULL);
-#else
-        sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
-        gSurface = new SurfaceTextureClient(texture);
-#endif
+            gSurface = control->getSurface();
+            CHECK(gSurface != NULL);
+        } else {
+            CHECK(useSurfaceTexAlloc);
+
+            sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
+            gSurface = new SurfaceTextureClient(texture);
+        }
     }
 
     DataSource::RegisterDefaultSniffers();
@@ -945,6 +970,17 @@
                     fprintf(stderr, "could not create extractor.\n");
                     return -1;
                 }
+
+                sp<MetaData> meta = extractor->getMetaData();
+
+                if (meta != NULL) {
+                    const char *mime;
+                    CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+                    if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
+                        syncInfoPresent = false;
+                    }
+                }
             }
 
             size_t numTracks = extractor->countTracks();
@@ -1032,12 +1068,12 @@
         }
     }
 
-    if (useSurfaceAlloc && !audioOnly) {
+    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
         gSurface.clear();
 
-#if USE_SURFACE_COMPOSER
-        composerClient->dispose();
-#endif
+        if (useSurfaceAlloc) {
+            composerClient->dispose();
+        }
     }
 
     client.disconnect();
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index f780afb..ee91c29 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -20,6 +20,11 @@
 #include <media/mediaplayer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
 
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
@@ -31,7 +36,7 @@
 using namespace android;
 
 struct MyStreamSource : public BnStreamSource {
-    // Caller retains ownership of fd.
+    // Object assumes ownership of fd.
     MyStreamSource(int fd);
 
     virtual void setListener(const sp<IStreamListener> &listener);
@@ -64,6 +69,8 @@
 }
 
 MyStreamSource::~MyStreamSource() {
+    close(mFd);
+    mFd = -1;
 }
 
 void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
@@ -99,6 +106,143 @@
         mListener->queueBuffer(index, n);
     }
 }
+////////////////////////////////////////////////////////////////////////////////
+
+struct MyConvertingStreamSource : public BnStreamSource {
+    MyConvertingStreamSource(const char *filename);
+
+    virtual void setListener(const sp<IStreamListener> &listener);
+    virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
+
+    virtual void onBufferAvailable(size_t index);
+
+protected:
+    virtual ~MyConvertingStreamSource();
+
+private:
+    Mutex mLock;
+    Condition mCondition;
+
+    sp<IStreamListener> mListener;
+    Vector<sp<IMemory> > mBuffers;
+
+    sp<MPEG2TSWriter> mWriter;
+
+    ssize_t mCurrentBufferIndex;
+    size_t mCurrentBufferOffset;
+
+    List<size_t> mBufferQueue;
+
+    static ssize_t WriteDataWrapper(void *me, const void *data, size_t size);
+    ssize_t writeData(const void *data, size_t size);
+
+    DISALLOW_EVIL_CONSTRUCTORS(MyConvertingStreamSource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+MyConvertingStreamSource::MyConvertingStreamSource(const char *filename)
+    : mCurrentBufferIndex(-1),
+      mCurrentBufferOffset(0) {
+    sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
+    CHECK(dataSource != NULL);
+
+    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    CHECK(extractor != NULL);
+
+    mWriter = new MPEG2TSWriter(
+            this, &MyConvertingStreamSource::WriteDataWrapper);
+
+    for (size_t i = 0; i < extractor->countTracks(); ++i) {
+        const sp<MetaData> &meta = extractor->getTrackMetaData(i);
+
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (strncasecmp("video/", mime, 6) && strncasecmp("audio/", mime, 6)) {
+            continue;
+        }
+
+        CHECK_EQ(mWriter->addSource(extractor->getTrack(i)), (status_t)OK);
+    }
+
+    CHECK_EQ(mWriter->start(), (status_t)OK);
+}
+
+MyConvertingStreamSource::~MyConvertingStreamSource() {
+}
+
+void MyConvertingStreamSource::setListener(
+        const sp<IStreamListener> &listener) {
+    mListener = listener;
+}
+
+void MyConvertingStreamSource::setBuffers(
+        const Vector<sp<IMemory> > &buffers) {
+    mBuffers = buffers;
+}
+
+ssize_t MyConvertingStreamSource::WriteDataWrapper(
+        void *me, const void *data, size_t size) {
+    return static_cast<MyConvertingStreamSource *>(me)->writeData(data, size);
+}
+
+ssize_t MyConvertingStreamSource::writeData(const void *data, size_t size) {
+    size_t totalWritten = 0;
+
+    while (size > 0) {
+        Mutex::Autolock autoLock(mLock);
+
+        if (mCurrentBufferIndex < 0) {
+            while (mBufferQueue.empty()) {
+                mCondition.wait(mLock);
+            }
+
+            mCurrentBufferIndex = *mBufferQueue.begin();
+            mCurrentBufferOffset = 0;
+
+            mBufferQueue.erase(mBufferQueue.begin());
+        }
+
+        sp<IMemory> mem = mBuffers.itemAt(mCurrentBufferIndex);
+
+        size_t copy = size;
+        if (copy + mCurrentBufferOffset > mem->size()) {
+            copy = mem->size() - mCurrentBufferOffset;
+        }
+
+        memcpy((uint8_t *)mem->pointer() + mCurrentBufferOffset, data, copy);
+        mCurrentBufferOffset += copy;
+
+        if (mCurrentBufferOffset == mem->size()) {
+            mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+            mCurrentBufferIndex = -1;
+        }
+
+        data = (const uint8_t *)data + copy;
+        size -= copy;
+
+        totalWritten += copy;
+    }
+
+    return (ssize_t)totalWritten;
+}
+
+void MyConvertingStreamSource::onBufferAvailable(size_t index) {
+    Mutex::Autolock autoLock(mLock);
+
+    mBufferQueue.push_back(index);
+    mCondition.signal();
+
+    if (mWriter->reachedEOS()) {
+        if (mCurrentBufferIndex >= 0) {
+            mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+            mCurrentBufferIndex = -1;
+        }
+
+        mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
+    }
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -139,6 +283,8 @@
 int main(int argc, char **argv) {
     android::ProcessState::self()->startThreadPool();
 
+    DataSource::RegisterDefaultSniffers();
+
     if (argc != 2) {
         fprintf(stderr, "Usage: %s filename\n", argv[0]);
         return 1;
@@ -159,10 +305,10 @@
     CHECK(control != NULL);
     CHECK(control->isValid());
 
-    CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
+    SurfaceComposerClient::openGlobalTransaction();
     CHECK_EQ(control->setLayer(30000), (status_t)OK);
     CHECK_EQ(control->show(), (status_t)OK);
-    CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+    SurfaceComposerClient::closeGlobalTransaction();
 
     sp<Surface> surface = control->getSurface();
     CHECK(surface != NULL);
@@ -173,17 +319,28 @@
 
     CHECK(service.get() != NULL);
 
-    int fd = open(argv[1], O_RDONLY);
-
-    if (fd < 0) {
-        fprintf(stderr, "Failed to open file '%s'.", argv[1]);
-        return 1;
-    }
-
     sp<MyClient> client = new MyClient;
 
+    sp<IStreamSource> source;
+
+    size_t len = strlen(argv[1]);
+    if (len >= 3 && !strcasecmp(".ts", &argv[1][len - 3])) {
+        int fd = open(argv[1], O_RDONLY);
+
+        if (fd < 0) {
+            fprintf(stderr, "Failed to open file '%s'.", argv[1]);
+            return 1;
+        }
+
+        source = new MyStreamSource(fd);
+    } else {
+        printf("Converting file to transport stream for streaming...\n");
+
+        source = new MyConvertingStreamSource(argv[1]);
+    }
+
     sp<IMediaPlayer> player =
-        service->create(getpid(), client, new MyStreamSource(fd), 0);
+        service->create(getpid(), client, source, 0);
 
     if (player != NULL) {
         player->setVideoSurface(surface);
@@ -196,9 +353,6 @@
         fprintf(stderr, "failed to instantiate player.\n");
     }
 
-    close(fd);
-    fd = -1;
-
     composerClient->dispose();
 
     return 0;
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index c0c4c17..7183267 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.Manifest;
-import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.Arrays;
@@ -136,17 +135,8 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (NetworkErrorException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "addAccount", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
-            } catch (UnsupportedOperationException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "addAccount", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "addAccount not supported");
+            } catch (Exception e) {
+                handleException(response, "addAccount", accountType, e);
             }
         }
 
@@ -167,17 +157,8 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (NetworkErrorException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "confirmCredentials", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
-            } catch (UnsupportedOperationException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "confirmCredentials", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "confirmCredentials not supported");
+            } catch (Exception e) {
+                handleException(response, "confirmCredentials", account.toString(), e);
             }
         }
 
@@ -197,21 +178,9 @@
                     Log.v(TAG, "getAuthTokenLabel: result "
                             + AccountManager.sanitizeResult(result));
                 }
-                if (result != null) {
-                    response.onResult(result);
-                }
-            } catch (IllegalArgumentException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "getAuthTokenLabel", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
-                        "unknown authTokenType");
-            } catch (UnsupportedOperationException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "getAuthTokenLabel", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "getAuthTokenTypeLabel not supported");
+                response.onResult(result);
+            } catch (Exception e) {
+                handleException(response, "getAuthTokenLabel", authTokenType, e);
             }
         }
 
@@ -234,17 +203,9 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (UnsupportedOperationException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "getAuthToken", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "getAuthToken not supported");
-            } catch (NetworkErrorException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "getAuthToken", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+            } catch (Exception e) {
+                handleException(response, "getAuthToken",
+                        account.toString() + "," + authTokenType, e);
             }
         }
 
@@ -267,17 +228,9 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (NetworkErrorException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "updateCredentials", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
-            } catch (UnsupportedOperationException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "updateCredentials", e);
-                }
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "updateCredentials not supported");
+            } catch (Exception e) {
+                handleException(response, "updateCredentials",
+                        account.toString() + "," + authTokenType, e);
             }
         }
 
@@ -290,9 +243,8 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (UnsupportedOperationException e) {
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "editProperties not supported");
+            } catch (Exception e) {
+                handleException(response, "editProperties", accountType, e);
             }
         }
 
@@ -305,11 +257,8 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (UnsupportedOperationException e) {
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "hasFeatures not supported");
-            } catch (NetworkErrorException e) {
-                response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+            } catch (Exception e) {
+                handleException(response, "hasFeatures", account.toString(), e);
             }
         }
 
@@ -322,15 +271,38 @@
                 if (result != null) {
                     response.onResult(result);
                 }
-            } catch (UnsupportedOperationException e) {
-                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                        "getAccountRemovalAllowed not supported");
-            } catch (NetworkErrorException e) {
-                response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+            } catch (Exception e) {
+                handleException(response, "getAccountRemovalAllowed", account.toString(), e);
             }
         }
     }
 
+    private void handleException(IAccountAuthenticatorResponse response, String method,
+            String data, Exception e) throws RemoteException {
+        if (e instanceof NetworkErrorException) {
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, method + "(" + data + ")", e);
+            }
+            response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+        } else if (e instanceof UnsupportedOperationException) {
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, method + "(" + data + ")", e);
+            }
+            response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
+                    method + " not supported");
+        } else if (e instanceof IllegalArgumentException) {
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, method + "(" + data + ")", e);
+            }
+            response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                    method + " not supported");
+        } else {
+            Log.w(TAG, method + "(" + data + ")", e);
+            response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
+                    method + " failed");
+        }
+    }
+
     private void checkBinderPermission() {
         final int uid = Binder.getCallingUid();
         final String perm = Manifest.permission.ACCOUNT_MANAGER;
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 7a465c1..491fcfe 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -890,7 +890,10 @@
         public AlertDialog create() {
             final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
             P.apply(dialog.mAlert);
-            dialog.setCanceledOnTouchOutside(P.mCancelable);
+            dialog.setCancelable(P.mCancelable);
+            if (P.mCancelable) {
+                dialog.setCanceledOnTouchOutside(true);
+            }
             dialog.setOnCancelListener(P.mOnCancelListener);
             if (P.mOnKeyListener != null) {
                 dialog.setOnKeyListener(P.mOnKeyListener);
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index cb03d2c..688cdfd 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -19,6 +19,7 @@
 import android.app.SearchableInfo;
 import android.app.ISearchManagerCallback;
 import android.content.ComponentName;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.os.Bundle;
 
@@ -26,6 +27,7 @@
 interface ISearchManager {
    SearchableInfo getSearchableInfo(in ComponentName launchActivity);
    List<SearchableInfo> getSearchablesInGlobalSearch();
+   List<ResolveInfo> getGlobalSearchActivities();
    ComponentName getGlobalSearchActivity();
    ComponentName getWebSearchActivity();
 }
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9cb57be..41eea2e 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -80,6 +80,7 @@
     private View mSearchPlate;
     private SearchView mSearchView;
     private Drawable mWorkingSpinner;
+    private View mCloseSearch;
 
     // interaction with searchable application
     private SearchableInfo mSearchable;
@@ -167,11 +168,18 @@
         SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar);
         searchBar.setSearchDialog(this);
         mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);
-        mSearchView.setSubmitButtonEnabled(true);
         mSearchView.setOnCloseListener(mOnCloseListener);
         mSearchView.setOnQueryTextListener(mOnQueryChangeListener);
         mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener);
 
+        mCloseSearch = findViewById(com.android.internal.R.id.closeButton);
+        mCloseSearch.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismiss();
+            }
+        });
+
         // TODO: Move the badge logic to SearchView or move the badge to search_bar.xml
         mBadgeLabel = (TextView) mSearchView.findViewById(com.android.internal.R.id.search_badge);
         mSearchAutoComplete = (AutoCompleteTextView)
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index aab087f..85a2fa8 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
@@ -374,6 +375,17 @@
             = "android.search.action.SEARCHABLES_CHANGED";
 
     /**
+     * Intent action to be broadcast to inform that the global search provider
+     * has changed. Normal components will have no need to handle this intent since
+     * they should be using API methods from this class to access the global search
+     * activity
+     *
+     * @hide
+     */
+    public final static String INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED
+            = "android.search.action.GLOBAL_SEARCH_ACTIVITY_CHANGED";
+
+    /**
      * Intent action broadcasted to inform that the search settings have changed in some way.
      * Either searchables have been enabled or disabled, or a different web search provider
      * has been chosen.
@@ -526,6 +538,21 @@
     }
 
     /**
+     * Returns a list of installed apps that handle the global search
+     * intent.
+     *
+     * @hide
+     */
+    public List<ResolveInfo> getGlobalSearchActivities() {
+        try {
+            return mService.getGlobalSearchActivities();
+        } catch (RemoteException ex) {
+            Log.e(TAG, "getGlobalSearchActivities() failed: " + ex);
+            return null;
+        }
+    }
+
+    /**
      * Gets the name of the global search activity.
      *
      * @hide
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a8c31f9..b993bd8 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1115,6 +1115,9 @@
         } else if (profile == BluetoothProfile.PAN) {
             BluetoothPan pan = new BluetoothPan(context, listener);
             return true;
+        } else if (profile == BluetoothProfile.HEALTH) {
+            BluetoothHealth health = new BluetoothHealth(context, listener);
+            return true;
         } else {
             return false;
         }
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
new file mode 100644
index 0000000..52efc07
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.annotation.SdkConstant;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Public API for Bluetooth Health Profile.
+ *
+ * <p>BluetoothHealth is a proxy object for controlling the Bluetooth
+ * Service via IPC.
+ *
+ * <p> Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothHealth proxy object. Use
+ * {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
+ * @hide
+ */
+public final class BluetoothHealth implements BluetoothProfile {
+    private static final String TAG = "BluetoothHealth";
+    private static final boolean DBG = false;
+
+    /**
+     * Health Profile Source Role - the health device.
+     */
+    public static final int SOURCE_ROLE = 1 << 0;
+
+    /**
+     * Health Profile Sink Role the device talking to the health device.
+     */
+    public static final int SINK_ROLE = 1 << 1;
+
+    /**
+     * Health Profile - Channel Type used - Reliable
+     */
+    public static final int CHANNEL_TYPE_RELIABLE = 10;
+
+    /**
+     * Health Profile - Channel Type used - Streaming
+     */
+    public static final int CHANNEL_TYPE_STREAMING = 11;
+
+    /**
+     * @hide
+     */
+    public static final int CHANNEL_TYPE_ANY = 12;
+
+    private final ArrayList<BluetoothHealthAppConfiguration> mAppConfigs =
+        new ArrayList<BluetoothHealthAppConfiguration>();
+
+    /**
+     * Register an application configuration that acts as a Health SINK.
+     * This is the configuration that will be used to communicate with health devices
+     * which will act as the {@link #SOURCE_ROLE}. This is an asynchronous call and so
+     * the callback is used to notify success or failure if the function returns true.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param name The friendly name associated with the application or configuration.
+     * @param dataType The dataType of the Source role of Health Profile to which
+     *                   the sink wants to connect to.
+     * @param callback A callback to indicate success or failure of the registration and
+     *               all operations done on this application configuration.
+     * @return If true, callback will be called.
+     */
+    public boolean registerSinkAppConfiguration(String name, int dataType,
+            IBluetoothHealthCallback callback) {
+        if (!isEnabled() || name == null) return false;
+
+        if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")");
+        return registerAppConfiguration(name, dataType, SINK_ROLE,
+                CHANNEL_TYPE_ANY, callback);
+    }
+
+    /**
+     * Register an application configuration that acts as a Health SINK or in a Health
+     * SOURCE role.This is an asynchronous call and so
+     * the callback is used to notify success or failure if the function returns true.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param name The friendly name associated with the application or configuration.
+     * @param dataType The dataType of the Source role of Health Profile.
+     * @param channelType The channel type. Will be one of
+     *                              {@link #CHANNEL_TYPE_RELIABLE}  or
+     *                              {@link #CHANNEL_TYPE_STREAMING}
+     * @param callback - A callback to indicate success or failure.
+     * @return If true, callback will be called.
+     * @hide
+     */
+    public boolean registerAppConfiguration(String name, int dataType, int role,
+            int channelType, IBluetoothHealthCallback callback) {
+        boolean result = false;
+        if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result;
+
+        if (DBG) log("registerApplication(" + name + ":" + dataType + ")");
+        BluetoothHealthAppConfiguration config =
+                new BluetoothHealthAppConfiguration(name, dataType, role, channelType,
+                callback);
+
+        if (mService != null) {
+            try {
+                result = mService.registerAppConfiguration(config);
+            } 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()));
+        }
+
+        if (result) mAppConfigs.add(config);
+        return result;
+    }
+
+    /**
+     * Unregister an application configuration that has been registered using
+     * {@link #registerSinkAppConfiguration}
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param config  The health app configuration
+     * @return Success or failure.
+     * @hide
+     */
+    public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
+        boolean result = false;
+        if (mService != null && isEnabled() && isValidAppConfig(config)) {
+            try {
+                result = mService.unregisterAppConfiguration(config);
+            } 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()));
+        }
+        if (result) mAppConfigs.remove(config);
+        return result;
+    }
+
+    /**
+     * Connect to a health device which has the {@link #SOURCE_ROLE}.
+     * This is an asynchrnous call. If this function returns true, the callback
+     * associated with the application configuration will be called.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param device The remote Bluetooth device.
+     * @param config The application configuration which has been registed using
+     *        {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+     * @return If true, the callback associated with the application config will be called.
+     */
+    public boolean connectChannelToSource(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config) {
+        if (mService != null && isEnabled() && isValidDevice(device) &&
+                isValidAppConfig(config)) {
+            try {
+                return mService.connectChannelToSource(device, config);
+            } 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;
+    }
+
+    /**
+     * Connect to a health device which has the {@link #SINK_ROLE}.
+     * This is an asynchronous call. If this function returns true, the callback
+     * associated with the application configuration will be called.
+     *
+     *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param device The remote Bluetooth device.
+     * @param config The application configuration which has been registed using
+     *        {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+     * @return If true, the callback associated with the application config will be called.
+     * @hide
+     */
+    public boolean connectChannelToSink(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config, int channelType) {
+        if (mService != null && isEnabled() && isValidDevice(device) &&
+                isValidAppConfig(config)) {
+            try {
+                return mService.connectChannelToSink(device, config, channelType);
+            } 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 connected health channel.
+     * This is an asynchronous call. If this function returns true, the callback
+     * associated with the application configuration will be called.
+     *
+     *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param device The remote Bluetooth device.
+     * @param config The application configuration which has been registed using
+     *        {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+     * @param fd The file descriptor that was associated with the channel.
+     * @return If true, the callback associated with the application config will be called.
+     * @hide
+     */
+    public boolean disconnectChannel(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+        if (mService != null && isEnabled() && isValidDevice(device) &&
+                isValidAppConfig(config)) {
+            try {
+                return mService.disconnectChannel(device, config, fd);
+            } 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 file descriptor of the main channel associated with the remote device
+     * and application configuration.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param device The remote Bluetooth health device
+     * @param config The application configuration
+     * @return null on failure, ParcelFileDescriptor on success.
+     */
+
+    public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config) {
+        if (mService != null && isEnabled() && isValidDevice(device) &&
+                isValidAppConfig(config)) {
+            try {
+                return mService.getMainChannelFd(device, config);
+            } 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 null;
+    }
+
+    /**
+     * Get the current connection state of the profile.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * This is not specific to any application configuration but represents the connection
+     * state of the local Bluetooth adapter with the remote device. This can be used
+     * by applications like status bar which would just like to know the state of the
+     * local adapter.
+     *
+     * @param device Remote bluetooth device.
+     * @return State of the profile connection. One of
+     *               {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
+     *               {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
+     */
+    public int getConnectionState(BluetoothDevice device) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getHealthDeviceConnectionState(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 STATE_DISCONNECTED;
+    }
+
+    /**
+     * Get connected devices for this specific profile.
+     *
+     * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * This is not specific to any application configuration but represents the connection
+     * state of the local Bluetooth adapter for this profile. This can be used
+     * by applications like status bar which would just like to know the state of the
+     * local adapter.
+     * @return List of devices. The list will be empty on error.
+     */
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getConnectedHealthDevices();
+            } 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");
+        return new ArrayList<BluetoothDevice>();
+    }
+
+    /**
+     * Get a list of devices that match any of the given connection
+     * states.
+     *
+     * <p> If none of the devices match any of the given states,
+     * an empty list will be returned.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     * This is not specific to any application configuration but represents the connection
+     * state of the local Bluetooth adapter for this profile. This can be used
+     * by applications like status bar which would just like to know the state of the
+     * local adapter.
+     *
+     * @param states Array of states. States can be one of
+     *              {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
+     *              {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
+     * @return List of devices. The list will be empty on error.
+     */
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getHealthDevicesMatchingConnectionStates(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");
+        return new ArrayList<BluetoothDevice>();
+    }
+
+     /** Health Channel Connection State - Disconnected */
+    public static final int STATE_CHANNEL_DISCONNECTED  = 0;
+    /** Health Channel Connection State - Connecting */
+    public static final int STATE_CHANNEL_CONNECTING    = 1;
+    /** Health Channel Connection State - Connected */
+    public static final int STATE_CHANNEL_CONNECTED     = 2;
+    /** Health Channel Connection State - Disconnecting */
+    public static final int STATE_CHANNEL_DISCONNECTING = 3;
+
+    /** Health App Configuration registration success */
+    public static final int APPLICATION_REGISTRATION_SUCCESS = 0;
+    /** Health App Configuration registration failure */
+    public static final int APPLICATION_REGISTRATION_FAILURE = 1;
+    /** Health App Configuration un-registration success */
+    public static final int APPLICATION_UNREGISTRATION_SUCCESS = 2;
+    /** Health App Configuration un-registration failure */
+    public static final int APPLICATION_UNREGISTRATION_FAILURE = 3;
+
+    private Context mContext;
+    private ServiceListener mServiceListener;
+    private IBluetooth mService;
+    BluetoothAdapter mAdapter;
+
+    /**
+     * Create a BluetoothHealth proxy object.
+     */
+    /*package*/ BluetoothHealth(Context mContext, ServiceListener l) {
+        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+        mServiceListener = l;
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        if (b != null) {
+            mService = IBluetooth.Stub.asInterface(b);
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, 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;
+        }
+    }
+
+    private boolean isEnabled() {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+
+        if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
+        log("Bluetooth is Not enabled");
+        return false;
+    }
+
+    private boolean isValidDevice(BluetoothDevice device) {
+        if (device == null) return false;
+
+        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+        return false;
+    }
+
+    private boolean isValidAppConfig(BluetoothHealthAppConfiguration config) {
+        if (!mAppConfigs.isEmpty() && mAppConfigs.contains(config)) return true;
+        log("Not a valid config: " + config);
+        return false;
+    }
+
+    private boolean checkAppParam(String name, int role, int channelType,
+            IBluetoothHealthCallback callback) {
+        if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) ||
+                (channelType != CHANNEL_TYPE_RELIABLE &&
+                channelType != CHANNEL_TYPE_STREAMING &&
+                channelType != CHANNEL_TYPE_ANY) || callback == null) {
+            return false;
+        }
+        if (role == SOURCE_ROLE && channelType == CHANNEL_TYPE_ANY) return false;
+        return true;
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl
new file mode 100644
index 0000000..bc9e54f
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+** 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.
+*/
+
+package android.bluetooth;
+
+parcelable BluetoothHealthAppConfiguration;
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
new file mode 100644
index 0000000..b87aea5
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.bluetooth;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The Bluetooth Health Application Configuration that is used in conjunction with
+ * the {@link BluetoothHealth} class. This class represents an application configuration
+ * that the Bluetooth Health third party application will register to communicate with the
+ * remote Bluetooth health device.
+ *
+ * @hide
+ */
+public final class BluetoothHealthAppConfiguration implements Parcelable {
+    private final String mName;
+    private final int mDataType;
+    private final int mRole;
+    private final int mChannelType;
+    private final IBluetoothHealthCallback mCallback;
+
+    /**
+     * Constructor to register the SINK role
+     *
+     * @param name Friendly name associated with the application configuration
+     * @param dataType Data Type of the remote Bluetooth Health device
+     * @param callback Callback associated with the application configuration.
+     */
+    BluetoothHealthAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) {
+        mName = name;
+        mDataType = dataType;
+        mRole = BluetoothHealth.SINK_ROLE;
+        mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY;
+        mCallback = callback;
+    }
+
+    /**
+     * Constructor to register the application configuration.
+     *
+     * @param name Friendly name associated with the application configuration
+     * @param dataType Data Type of the remote Bluetooth Health device
+     * @param role {@link BluetoothHealth.SOURCE_ROLE} or
+     *                     {@link BluetoothHealth.SINK_ROLE}
+     * @param callback Callback associated with the application configuration.
+     */
+    BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType,
+            IBluetoothHealthCallback callback) {
+        mName = name;
+        mDataType = dataType;
+        mRole = role;
+        mChannelType = channelType;
+        mCallback = callback;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof BluetoothHealthAppConfiguration) {
+            BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o;
+            // config.getName() can never be NULL
+            return mName.equals(config.getName()) &&
+                    mDataType == config.getDataType() &&
+                    mRole == config.getRole() &&
+                    mChannelType == config.getChannelType() &&
+                    mCallback.equals(config.getCallback());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + (mName != null ? mName.hashCode() : 0);
+        result = 31 * result + mDataType;
+        result = 31 * result + mRole;
+        result = 31 * result + mChannelType;
+        result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "BluetoothHealthAppConfiguration [mName = " + mName +
+            ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " +
+            mChannelType +  ",callback=" + mCallback +"]";
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Return the data type associated with this application configuration.
+     *
+     * @return dataType
+     */
+    public int getDataType() {
+        return mDataType;
+    }
+
+    /**
+     * Return the name of the application configuration.
+     *
+     * @return String name
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Return the role associated with this application configuration.
+     *
+     * @return One of {@link BluetoothHealth#SOURCE_ROLE} or
+     *                         {@link BluetoothHealth#SINK_ROLE}
+     */
+    public int getRole() {
+        return mRole;
+    }
+
+    /**
+     * Return the channel type associated with this application configuration.
+     *
+     * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or
+     *                         {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or
+     *                         {@link BluetoothHealth#CHANNEL_TYPE_ANY}.
+     */
+    public int getChannelType() {
+        return mChannelType;
+    }
+
+    /**
+     * Return the callback associated with this application configuration.
+     *
+     * @return IBluetoothHealthCallback
+     */
+    public IBluetoothHealthCallback getCallback() {
+        return mCallback;
+    }
+
+    public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR =
+        new Parcelable.Creator<BluetoothHealthAppConfiguration>() {
+        public BluetoothHealthAppConfiguration createFromParcel(Parcel in) {
+            String name = in.readString();
+            int type = in.readInt();
+            int role = in.readInt();
+            int channelType = in.readInt();
+            IBluetoothHealthCallback callback =
+                IBluetoothHealthCallback.Stub.asInterface(in.readStrongBinder());
+            return new BluetoothHealthAppConfiguration(name, type, role, channelType,
+                    callback);
+        }
+        public BluetoothHealthAppConfiguration[] newArray(int size) {
+            return new BluetoothHealthAppConfiguration[size];
+        }
+    };
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mName);
+        out.writeInt(mDataType);
+        out.writeInt(mRole);
+        out.writeInt(mChannelType);
+        out.writeStrongInterface(mCallback);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 22555f0..6cd81fd 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -65,16 +65,22 @@
     public static final int A2DP = 2;
 
     /**
+     * Health Profile
+     * @hide
+     */
+    public static final int HEALTH = 3;
+
+    /**
      * Input Device Profile
      * @hide
      */
-    public static final int INPUT_DEVICE = 3;
+    public static final int INPUT_DEVICE = 4;
 
     /**
      * PAN Profile
      * @hide
      */
-    public static final int PAN = 4;
+    public static final int PAN = 5;
 
     /**
      * Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index d25f5d0..28b09b6 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -18,7 +18,9 @@
 
 import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
 import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
 
 /**
  * System private API for talking with the Bluetooth service.
@@ -98,5 +100,17 @@
     boolean connectPanDevice(in BluetoothDevice device);
     boolean disconnectPanDevice(in BluetoothDevice device);
 
+    // HDP profile APIs
+    boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config);
+    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, in ParcelFileDescriptor fd);
+    ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+    List<BluetoothDevice> getConnectedHealthDevices();
+    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
+    int getHealthDeviceConnectionState(in BluetoothDevice device);
+
     void sendConnectionStateChange(in BluetoothDevice device, int state, int prevState);
 }
diff --git a/core/java/android/bluetooth/IBluetoothHealthCallback.aidl b/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
new file mode 100644
index 0000000..9fe5335
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.os.ParcelFileDescriptor;
+
+/**
+ *@hide
+ */
+interface IBluetoothHealthCallback
+{
+    void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
+    void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
+        in BluetoothDevice device, int prevState, int newState, in ParcelFileDescriptor fd);
+}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e927f6c..208869b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1573,7 +1573,7 @@
 
         boolean hardwareAccelerated = sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
-                false);
+                owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
 
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 11068e5..1205da7 100755
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -40,6 +40,12 @@
     public long cacheSize;
 
     /**
+     * Size of the secure container on external storage holding the
+     * application's code.
+     */
+    public long externalCodeSize;
+
+    /**
      * Size of the external data used by the application (e.g.,
      * <sdcard>/Android/data/<app>)
      */
@@ -80,6 +86,8 @@
         sb.append(dataSize);
         sb.append(",cacheSize=");
         sb.append(cacheSize);
+        sb.append(",externalCodeSize=");
+        sb.append(externalCodeSize);
         sb.append(",externalDataSize=");
         sb.append(externalDataSize);
         sb.append(",externalCacheSize=");
@@ -100,6 +108,7 @@
         codeSize = source.readLong();
         dataSize = source.readLong();
         cacheSize = source.readLong();
+        externalCodeSize = source.readLong();
         externalDataSize = source.readLong();
         externalCacheSize = source.readLong();
         externalMediaSize = source.readLong();
@@ -111,6 +120,7 @@
         codeSize = pStats.codeSize;
         dataSize = pStats.dataSize;
         cacheSize = pStats.cacheSize;
+        externalCodeSize = pStats.externalCodeSize;
         externalDataSize = pStats.externalDataSize;
         externalCacheSize = pStats.externalCacheSize;
         externalMediaSize = pStats.externalMediaSize;
@@ -126,6 +136,7 @@
         dest.writeLong(codeSize);
         dest.writeLong(dataSize);
         dest.writeLong(cacheSize);
+        dest.writeLong(externalCodeSize);
         dest.writeLong(externalDataSize);
         dest.writeLong(externalCacheSize);
         dest.writeLong(externalMediaSize);
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index acf2f2f1..1c9285e 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -432,17 +432,17 @@
             // compatible with large screens, so diddle it.
             CompatibilityInfo.computeCompatibleScaling(inoutDm, inoutDm);
         } else {
-            inoutDm.widthPixels = inoutDm.unscaledWidthPixels;
-            inoutDm.heightPixels = inoutDm.unscaledHeightPixels;
+            inoutDm.widthPixels = inoutDm.noncompatWidthPixels;
+            inoutDm.heightPixels = inoutDm.noncompatHeightPixels;
         }
 
         if (isScalingRequired()) {
             float invertedRatio = applicationInvertedScale;
-            inoutDm.density *= invertedRatio;
+            inoutDm.density = inoutDm.noncompatDensity * invertedRatio;
             inoutDm.densityDpi = (int)((inoutDm.density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
-            inoutDm.scaledDensity *= invertedRatio;
-            inoutDm.xdpi *= invertedRatio;
-            inoutDm.ydpi *= invertedRatio;
+            inoutDm.scaledDensity = inoutDm.noncompatScaledDensity * invertedRatio;
+            inoutDm.xdpi = inoutDm.noncompatXdpi * invertedRatio;
+            inoutDm.ydpi = inoutDm.noncompatYdpi * invertedRatio;
             inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertedRatio + 0.5f);
             inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertedRatio + 0.5f);
         }
@@ -471,8 +471,8 @@
      * @return Returns the scaling factor for the window.
      */
     public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
-        final int width = dm.unscaledWidthPixels;
-        final int height = dm.unscaledHeightPixels;
+        final int width = dm.noncompatWidthPixels;
+        final int height = dm.noncompatHeightPixels;
         int shortSize, longSize;
         if (width < height) {
             shortSize = width;
@@ -532,7 +532,9 @@
         sb.append(applicationDensity);
         sb.append("dpi");
         if (isScalingRequired()) {
-            sb.append(" scaling");
+            sb.append(" ");
+            sb.append(applicationScale);
+            sb.append("x");
         }
         if (!supportsScreen()) {
             sb.append(" resizing");
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index bd8b1a4..324c9fd 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1416,23 +1416,19 @@
             }
             if (metrics != null) {
                 mMetrics.setTo(metrics);
-                // NOTE: We should re-arrange this code to create a Display
-                // with the CompatibilityInfo that is used everywhere we deal
-                // with the display in relation to this app, rather than
-                // doing the conversion here.  This impl should be okay because
-                // we make sure to return a compatible display in the places
-                // where there are public APIs to retrieve the display...  but
-                // it would be cleaner and more maintainble to just be
-                // consistently dealing with a compatible display everywhere in
-                // the framework.
-                if (mCompatibilityInfo != null) {
-                    mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
-                }
             }
+            // NOTE: We should re-arrange this code to create a Display
+            // with the CompatibilityInfo that is used everywhere we deal
+            // with the display in relation to this app, rather than
+            // doing the conversion here.  This impl should be okay because
+            // we make sure to return a compatible display in the places
+            // where there are public APIs to retrieve the display...  but
+            // it would be cleaner and more maintainble to just be
+            // consistently dealing with a compatible display everywhere in
+            // the framework.
             if (mCompatibilityInfo != null) {
                 mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
             }
-            mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
             int configChanges = 0xfffffff;
             if (config != null) {
                 mTmpConfig.setTo(config);
@@ -1448,6 +1444,7 @@
             if (mConfiguration.locale == null) {
                 mConfiguration.locale = Locale.getDefault();
             }
+            mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
             String locale = null;
             if (mConfiguration.locale != null) {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 0be1776..8a42693 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -288,7 +288,8 @@
      * you can call {@link #reconnect()} to reclaim the camera.
      *
      * <p>This must be done before calling
-     * {@link android.media.MediaRecorder#setCamera(Camera)}.
+     * {@link android.media.MediaRecorder#setCamera(Camera)}. This cannot be
+     * called after recording starts.
      *
      * <p>If you are not recording video, you probably do not need this method.
      *
@@ -301,6 +302,11 @@
      * Camera objects are locked by default unless {@link #unlock()} is
      * called.  Normally {@link #reconnect()} is used instead.
      *
+     * <p>Since API level 13, camera is automatically locked for applications in
+     * {@link android.media.MediaRecorder#start()}. Applications can use the
+     * camera (ex: zoom) after recording starts. There is no need to call this
+     * after recording starts or stops.
+     *
      * <p>If you are not recording video, you probably do not need this method.
      *
      * @throws RuntimeException if the camera cannot be re-locked (for
@@ -315,9 +321,10 @@
      * which will re-acquire the lock and allow you to continue using the
      * camera.
      *
-     * <p>This must be done after {@link android.media.MediaRecorder} is
-     * done recording if {@link android.media.MediaRecorder#setCamera(Camera)}
-     * was used.
+     * <p>Since API level 13, camera is automatically locked for applications in
+     * {@link android.media.MediaRecorder#start()}. Applications can use the
+     * camera (ex: zoom) after recording starts. There is no need to call this
+     * after recording starts or stops.
      *
      * <p>If you are not recording video, you probably do not need this method.
      *
@@ -827,7 +834,9 @@
      * <p>This method is only valid when preview is active (after
      * {@link #startPreview()}).  Preview will be stopped after the image is
      * taken; callers must call {@link #startPreview()} again if they want to
-     * re-start preview or take more pictures.
+     * re-start preview or take more pictures. This should not be called between
+     * {@link android.media.MediaRecorder#start()} and
+     * {@link android.media.MediaRecorder#stop()}.
      *
      * <p>After calling this method, you must not call {@link #startPreview()}
      * or take another picture until the JPEG callback has returned.
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 2b9c082..9bab797 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -82,11 +82,8 @@
     /* Clears default preferences and permissions for the package */
     void clearDefaults(String packageName);
 
-    /* Sets the current primary USB function. */
-    void setPrimaryFunction(String functions);
-
-    /* Sets the default primary USB function. */
-    void setDefaultFunction(String functions);
+    /* Sets the current USB function. */
+    void setCurrentFunction(String function, boolean makeDefault);
 
     /* Sets the file path for USB mass storage backing file. */
     void setMassStorageBackingFile(String path);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index a828a23..67d200c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -408,32 +408,18 @@
     }
 
     /**
-     * Sets the primary USB function.
+     * Sets the current USB function.
      *
      * @param function name of the USB function
+     * @param makeDefault true if this should be set as the default
      *
      * {@hide}
      */
-    public void setPrimaryFunction(String function) {
+    public void setCurrentFunction(String function, boolean makeDefault) {
         try {
-            mService.setPrimaryFunction(function);
+            mService.setCurrentFunction(function, makeDefault);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setPrimaryFunction", e);
-        }
-    }
-
-    /**
-     * Sets the default primary USB function.
-     *
-     * @param function name of the USB function
-     *
-     * {@hide}
-     */
-    public void setDefaultFunction(String function) {
-        try {
-            mService.setDefaultFunction(function);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setDefaultFunction", e);
+            Log.e(TAG, "RemoteException in setCurrentFunction", e);
         }
     }
 
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index df8cf9a..e10f218 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -47,6 +47,7 @@
     private static final int DO_APP_PRIVATE_COMMAND = 100;
     private static final int DO_TOGGLE_SOFT_INPUT = 105;
     private static final int DO_FINISH_SESSION = 110;
+    private static final int DO_VIEW_CLICKED = 115;
 
     HandlerCaller mCaller;
     InputMethodSession mInputMethodSession;
@@ -133,6 +134,10 @@
                 mInputMethodSession = null;
                 return;
             }
+            case DO_VIEW_CLICKED: {
+                mInputMethodSession.viewClicked(msg.arg1 == 1);
+                return;
+            }
         }
         Log.w(TAG, "Unhandled message code: " + msg.what);
     }
@@ -167,7 +172,11 @@
                 oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                 candidatesStart, candidatesEnd));
     }
-    
+
+    public void viewClicked(boolean focusChanged) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
+    }
+
     public void updateCursor(Rect newCursor) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UPDATE_CURSOR,
                 newCursor));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index feb246e..9481a88 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -488,7 +488,15 @@
             InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
                     newSelStart, newSelEnd, candidatesStart, candidatesEnd);
         }
-        
+
+        @Override
+        public void viewClicked(boolean focusChanged) {
+            if (!isEnabled()) {
+                return;
+            }
+            InputMethodService.this.onViewClicked(focusChanged);
+        }
+
         /**
          * Call {@link InputMethodService#onUpdateCursor
          * InputMethodService.onUpdateCursor()}.
@@ -1609,6 +1617,16 @@
     }
 
     /**
+     * Called when the user tapped or clicked a text view.
+     * IMEs can't rely on this method being called because this was not part of the original IME
+     * protocol, so applications with custom text editing written before this method appeared will
+     * not call to inform the IME of this interaction.
+     * @param focusChanged true if the user changed the focused view by this click.
+     */
+    public void onViewClicked(boolean focusChanged) {
+    }
+
+    /**
      * Called when the application has reported a new location of its text
      * cursor.  This is only called if explicitly requested by the input method.
      * The default implementation does nothing.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2242e9e..ce6f697 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -164,6 +164,12 @@
     public static final String EXTRA_ERRORED_TETHER = "erroredArray";
 
     /**
+     * The absence of APN..
+     * @hide
+     */
+    public static final int TYPE_NONE        = -1;
+
+    /**
      * The Default Mobile data connection.  When active, all data traffic
      * will use this connection by default.
      */
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index c49c019..445b2f7 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -117,13 +117,14 @@
 
         PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
         mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
+        mDhcpRenewWakeLock.setReferenceCounted(false);
 
         mBroadcastReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 //DHCP renew
                 if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this);
-                //acquire a 40s wakelock to finish DHCP renewal
+                //Lock released after 40s in worst case scenario
                 mDhcpRenewWakeLock.acquire(40000);
                 sendMessage(CMD_RENEW_DHCP);
             }
@@ -166,6 +167,7 @@
             switch (message.what) {
                 case CMD_RENEW_DHCP:
                     Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
+                    mDhcpRenewWakeLock.release();
                     break;
                 case SM_QUIT_CMD:
                     mContext.unregisterReceiver(mBroadcastReceiver);
@@ -268,10 +270,12 @@
                         /* Notify controller before starting DHCP */
                         mController.sendMessage(CMD_PRE_DHCP_ACTION);
                         transitionTo(mWaitBeforeRenewalState);
+                        //mDhcpRenewWakeLock is released in WaitBeforeRenewalState
                     } else {
                         if (!runDhcp(DhcpAction.RENEW)) {
                             transitionTo(mStoppedState);
                         }
+                        mDhcpRenewWakeLock.release();
                     }
                     break;
                 case CMD_START_DHCP:
@@ -318,6 +322,10 @@
             }
             return retValue;
         }
+        @Override
+        public void exit() {
+            mDhcpRenewWakeLock.release();
+        }
     }
 
     private boolean runDhcp(DhcpAction dhcpAction) {
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 6f92247..a866436 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -53,6 +53,7 @@
     private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
 
+    private static boolean mLinkUp;
     private LinkProperties mLinkProperties;
     private LinkCapabilities mLinkCapabilities;
     private NetworkInfo mNetworkInfo;
@@ -74,8 +75,25 @@
             mTracker = tracker;
         }
 
-        public void interfaceLinkStatusChanged(String iface, boolean up) {
-            Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+        public void interfaceStatusChanged(String iface, boolean up) {
+            Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
+        }
+
+        public void interfaceLinkStateChanged(String iface, boolean up) {
+            if (mIface.equals(iface) && mLinkUp != up) {
+                Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+                mLinkUp = up;
+
+                // use DHCP
+                if (up) {
+                    mTracker.reconnect();
+                } else {
+                    NetworkUtils.stopDhcp(mIface);
+                    mTracker.mNetworkInfo.setIsAvailable(false);
+                    mTracker.mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,
+                                                           null, null);
+                }
+            }
         }
 
         public void interfaceAdded(String iface) {
@@ -91,6 +109,7 @@
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
         mLinkProperties = new LinkProperties();
         mLinkCapabilities = new LinkCapabilities();
+        mLinkUp = false;
 
         mNetworkInfo.setIsAvailable(false);
         setTeardownRequested(false);
@@ -182,14 +201,11 @@
         // register for notifications from NetworkManagement Service
         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
         INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-        mInterfaceObserver = new InterfaceObserver(this);
-        try {
-            service.registerObserver(mInterfaceObserver);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Could not register InterfaceObserver " + e);
-        }
 
-        // connect to an ethernet interface that already exists
+        mInterfaceObserver = new InterfaceObserver(this);
+
+        // enable and try to connect to an ethernet interface that
+        // already exists
         sIfaceMatch = context.getResources().getString(
             com.android.internal.R.string.config_ethernet_iface_regex);
         try {
@@ -197,6 +213,8 @@
             for (String iface : ifaces) {
                 if (iface.matches(sIfaceMatch)) {
                     mIface = iface;
+                    InterfaceConfiguration config = service.getInterfaceConfig(iface);
+                    mLinkUp = config.isActive();
                     reconnect();
                     break;
                 }
@@ -204,6 +222,12 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Could not get list of interfaces " + e);
         }
+
+        try {
+            service.registerObserver(mInterfaceObserver);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not register InterfaceObserver " + e);
+        }
     }
 
     /**
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index d30b63d..4436e6e 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -23,12 +23,21 @@
  */
 interface INetworkManagementEventObserver {
     /**
-     * Interface link status has changed.
+     * Interface configuration status has changed.
      *
      * @param iface The interface.
-     * @param link True if link is up.
+     * @param up True if the interface has been enabled.
      */
-    void interfaceLinkStatusChanged(String iface, boolean link);
+    void interfaceStatusChanged(String iface, boolean up);
+
+    /**
+     * Interface physical-layer link state has changed.  For Ethernet,
+     * this method is invoked when the cable is plugged in or unplugged.
+     *
+     * @param iface The interface.
+     * @param up  True if the physical link-layer connection signal is valid.
+     */
+    void interfaceLinkStateChanged(String iface, boolean up);
 
     /**
      * An interface has been added to the system
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 91af16d..593b2b7 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -16,14 +16,21 @@
 
 package android.net;
 
+import static android.content.pm.PackageManager.GET_SIGNATURES;
 import static android.text.format.Time.MONTH_DAY;
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
 import android.os.RemoteException;
 import android.text.format.Time;
 
+import com.google.android.collect.Sets;
+
 import java.io.PrintWriter;
+import java.util.HashSet;
 
 /**
  * Manager for creating and modifying network policy rules.
@@ -42,6 +49,8 @@
     /** Reject traffic on metered networks. */
     public static final int RULE_REJECT_METERED = 0x1;
 
+    private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
+
     /**
      * {@link Intent} action launched when user selects {@link NetworkPolicy}
      * warning notification.
@@ -210,8 +219,37 @@
      * usually to protect critical system services.
      */
     public static boolean isUidValidForPolicy(Context context, int uid) {
-        return (uid >= android.os.Process.FIRST_APPLICATION_UID
-                && uid <= android.os.Process.LAST_APPLICATION_UID);
+        // first, quick-reject non-applications
+        if (uid < android.os.Process.FIRST_APPLICATION_UID
+                || uid > android.os.Process.LAST_APPLICATION_UID) {
+            return false;
+        }
+
+        if (!ALLOW_PLATFORM_APP_POLICY) {
+            final PackageManager pm = context.getPackageManager();
+            final HashSet<Signature> systemSignature;
+            try {
+                systemSignature = Sets.newHashSet(
+                        pm.getPackageInfo("android", GET_SIGNATURES).signatures);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException("problem finding system signature", e);
+            }
+
+            try {
+                // reject apps signed with platform cert
+                for (String packageName : pm.getPackagesForUid(uid)) {
+                    final HashSet<Signature> packageSignature = Sets.newHashSet(
+                            pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
+                    if (packageSignature.containsAll(systemSignature)) {
+                        return false;
+                    }
+                }
+            } catch (NameNotFoundException e) {
+            }
+        }
+
+        // nothing found above; we can apply policy to UID
+        return true;
     }
 
     /** {@hide} */
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index cb47193..2b59dba 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,14 +16,18 @@
 
 package android.net;
 
+import android.app.DownloadManager;
+import android.app.backup.BackupManager;
 import android.content.Context;
+import android.media.MediaPlayer;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
-import dalvik.system.BlockGuard;
+import com.android.server.NetworkManagementSocketTagger;
 
+import dalvik.system.SocketTagger;
 import java.net.Socket;
 import java.net.SocketException;
 
@@ -50,6 +54,27 @@
     public static final int UID_REMOVED = -4;
 
     /**
+     * Default tag value for {@link DownloadManager} traffic.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001;
+
+    /**
+     * Default tag value for {@link MediaPlayer} traffic.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002;
+
+    /**
+     * Default tag value for {@link BackupManager} traffic.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003;
+
+    /**
      * Snapshot of {@link NetworkStats} when the currently active profiling
      * session started, or {@code null} if no session active.
      *
@@ -67,12 +92,20 @@
      * Changes only take effect during subsequent calls to
      * {@link #tagSocket(Socket)}.
      */
+    public static void setThreadStatsTag(int tag) {
+        NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+    }
+
+    /**
+     * @deprecated unsupported, will eventually be removed
+     */
+    @Deprecated
     public static void setThreadStatsTag(String tag) {
-        BlockGuard.setThreadSocketStatsTag(tag);
+        setThreadStatsTag(tag.hashCode());
     }
 
     public static void clearThreadStatsTag() {
-        BlockGuard.setThreadSocketStatsTag(null);
+        NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
     }
 
     /**
@@ -89,12 +122,12 @@
      * {@hide}
      */
     public static void setThreadStatsUid(int uid) {
-        BlockGuard.setThreadSocketStatsUid(uid);
+        NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
     }
 
     /** {@hide} */
     public static void clearThreadStatsUid() {
-        BlockGuard.setThreadSocketStatsUid(-1);
+        NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
     }
 
     /**
@@ -103,18 +136,18 @@
      * parameters. When finished, call {@link #untagSocket(Socket)} to remove
      * statistics parameters.
      *
-     * @see #setThreadStatsTag(String)
+     * @see #setThreadStatsTag(int)
      * @see #setThreadStatsUid(int)
      */
     public static void tagSocket(Socket socket) throws SocketException {
-        BlockGuard.tagSocketFd(socket.getFileDescriptor$());
+        SocketTagger.get().tag(socket);
     }
 
     /**
      * Remove any statistics parameters from the given {@link Socket}.
      */
     public static void untagSocket(Socket socket) throws SocketException {
-        BlockGuard.untagSocketFd(socket.getFileDescriptor$());
+        SocketTagger.get().untag(socket);
     }
 
     /**
diff --git a/core/java/android/net/http/HttpResponseCache.java b/core/java/android/net/http/HttpResponseCache.java
index b5d64e4..5f65dfa 100644
--- a/core/java/android/net/http/HttpResponseCache.java
+++ b/core/java/android/net/http/HttpResponseCache.java
@@ -70,12 +70,15 @@
  * the hit rate, but it may also just waste filesystem space!
  *
  * <p>For some applications it may be preferable to create the cache in the
- * external storage directory. Although it often has more free space, external
- * storage is optional and&#8212;even if available&#8212;can disappear during
- * use. Retrieve the external cache directory using {@link Context#getExternalCacheDir()}. If this method
- * returns null, your application should fall back to either not caching or
- * caching on non-external storage. If the external storage is removed during
- * use, the cache hit rate will drop to zero and ongoing cache reads will fail.
+ * external storage directory. <strong>There are no access controls on the
+ * external storage directory so it should not be used for caches that could
+ * contain private data.</strong> Although it often has more free space,
+ * external storage is optional and&#8212;even if available&#8212;can disappear
+ * during use. Retrieve the external cache directory using {@link
+ * Context#getExternalCacheDir()}. If this method returns null, your application
+ * should fall back to either not caching or caching on non-external storage. If
+ * the external storage is removed during use, the cache hit rate will drop to
+ * zero and ongoing cache reads will fail.
  *
  * <p>Flushing the cache forces its data to the filesystem. This ensures that
  * all responses written to the cache will be readable the next time the
@@ -214,7 +217,7 @@
      */
     public void flush() {
         try {
-            delegate.getCache().flush(); // TODO: fix flush() to not throw?
+            delegate.getCache().flush();
         } catch (IOException ignored) {
         }
     }
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 5079c23..f35002a 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -16,15 +16,19 @@
 
 package android.net.http;
 
+import android.content.Context;
 import android.os.Bundle;
+import android.text.format.DateFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
 
+import java.security.cert.X509Certificate;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Vector;
 
-import java.security.cert.X509Certificate;
-
 import com.android.org.bouncycastle.asn1.DERObjectIdentifier;
 import com.android.org.bouncycastle.asn1.x509.X509Name;
 
@@ -58,7 +62,7 @@
      */
     private Date mValidNotAfter;
 
-     /**
+    /**
      * Bundle key names
      */
     private static final String ISSUED_TO = "issued-to";
@@ -108,8 +112,10 @@
      * Creates a new SSL certificate object
      * @param issuedTo The entity this certificate is issued to
      * @param issuedBy The entity that issued this certificate
-     * @param validNotBefore The not-before date from the certificate validity period in ISO 8601 format
-     * @param validNotAfter The not-after date from the certificate validity period in ISO 8601 format
+     * @param validNotBefore The not-before date from the certificate
+     *     validity period in ISO 8601 format
+     * @param validNotAfter The not-after date from the certificate
+     *     validity period in ISO 8601 format
      * @deprecated Use {@link #SslCertificate(X509Certificate)}
      */
     @Deprecated
@@ -202,9 +208,8 @@
      * @return A string representation of this certificate for debugging
      */
     public String toString() {
-        return
-            "Issued to: " + mIssuedTo.getDName() + ";\n" +
-            "Issued by: " + mIssuedBy.getDName() + ";\n";
+        return ("Issued to: " + mIssuedTo.getDName() + ";\n"
+                + "Issued by: " + mIssuedBy.getDName() + ";\n");
     }
 
     /**
@@ -328,4 +333,65 @@
             return mUName != null ? mUName : "";
         }
     }
+
+    /**
+     * Inflates the SSL certificate view (helper method).
+     * @return The resultant certificate view with issued-to, issued-by,
+     * issued-on, expires-on, and possibly other fields set.
+     * If the input certificate is null, returns null.
+     *
+     * @hide Used by Browser and Settings
+     */
+    public View inflateCertificateView(Context context) {
+        LayoutInflater factory = LayoutInflater.from(context);
+
+        View certificateView = factory.inflate(
+            com.android.internal.R.layout.ssl_certificate, null);
+
+        // issued to:
+        SslCertificate.DName issuedTo = getIssuedTo();
+        if (issuedTo != null) {
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.to_common))
+                .setText(issuedTo.getCName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org))
+                .setText(issuedTo.getOName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org_unit))
+                .setText(issuedTo.getUName());
+        }
+
+        // issued by:
+        SslCertificate.DName issuedBy = getIssuedBy();
+        if (issuedBy != null) {
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.by_common))
+                .setText(issuedBy.getCName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org))
+                .setText(issuedBy.getOName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org_unit))
+                .setText(issuedBy.getUName());
+        }
+
+        // issued on:
+        String issuedOn = formatCertificateDate(context, getValidNotBeforeDate());
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.issued_on))
+            .setText(issuedOn);
+
+        // expires on:
+        String expiresOn = formatCertificateDate(context, getValidNotAfterDate());
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.expires_on))
+            .setText(expiresOn);
+
+        return certificateView;
+    }
+
+    /**
+     * Formats the certificate date to a properly localized date string.
+     * @return Properly localized version of the certificate date string and
+     * the "" if it fails to localize.
+     */
+    private String formatCertificateDate(Context context, Date certificateDate) {
+        if (certificateDate == null) {
+            return "";
+        }
+        return DateFormat.getDateFormat(context).format(certificateDate);
+    }
 }
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index e1b9deb..1e1cb49 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -59,36 +59,97 @@
     /**
      * The SSL certificate associated with the error set
      */
-    SslCertificate mCertificate;
+    final SslCertificate mCertificate;
+
+    /**
+     * The URL associated with the error set.
+     */
+    final String mUrl;
 
     /**
      * Creates a new SSL error set object
      * @param error The SSL error
      * @param certificate The associated SSL certificate
+     * @deprecated Use {@link #SslError(int, SslCertificate, String)}
      */
+    @Deprecated
     public SslError(int error, SslCertificate certificate) {
         addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
         mCertificate = certificate;
+        mUrl = "";
     }
 
     /**
      * Creates a new SSL error set object
      * @param error The SSL error
      * @param certificate The associated SSL certificate
+     * @deprecated Use {@link #SslError(int, X509Certificate, String)}
      */
+    @Deprecated
     public SslError(int error, X509Certificate certificate) {
         addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
         mCertificate = new SslCertificate(certificate);
+        mUrl = "";
     }
 
     /**
-     * @return The SSL certificate associated with the error set
+     * Creates a new SSL error set object
+     * @param error The SSL error
+     * @param certificate The associated SSL certificate
+     * @param url The associated URL.
+     */
+    public SslError(int error, SslCertificate certificate, String url) {
+        addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
+        mCertificate = certificate;
+        if (url == null) {
+            throw new NullPointerException("url is null.");
+        }
+        mUrl = url;
+    }
+
+    /**
+     * Creates a new SSL error set object
+     * @param error The SSL error
+     * @param certificate The associated SSL certificate
+     * @param url The associated URL.
+     */
+    public SslError(int error, X509Certificate certificate, String url) {
+        addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
+        mCertificate = new SslCertificate(certificate);
+        if (url == null) {
+            throw new NullPointerException("url is null.");
+        }
+        mUrl = url;
+    }
+
+    /**
+     * @return The SSL certificate associated with the error set, non-null.
      */
     public SslCertificate getCertificate() {
         return mCertificate;
     }
 
     /**
+     * @return The URL associated with the error set, non-null.
+     * "" if one of the deprecated constructors is used.
+     */
+    public String getUrl() {
+        return mUrl;
+    }
+
+    /**
      * Adds the SSL error to the error set
      * @param error The SSL error to add
      * @return True iff the error being added is a known SSL error
@@ -137,6 +198,7 @@
      */
     public String toString() {
         return "primary error: " + getPrimaryError() +
-            " certificate: " + getCertificate();
+            " certificate: " + getCertificate() +
+            "  on URL: " + getUrl();
     }
 }
diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
index 3f8b856..0c2a2fd 100755
--- a/core/java/android/nfc/INfcAdapterExtras.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -16,7 +16,6 @@
 
 package android.nfc;
 
-import android.nfc.ApduList;
 import android.os.Bundle;
 
 
@@ -29,4 +28,5 @@
     Bundle transceive(in byte[] data_in);
     int getCardEmulationRoute();
     void setCardEmulationRoute(int route);
+    void authenticate(in byte[] token);
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1b28aa2..6c7c58d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -278,6 +278,16 @@
 
         /**
          * Current version under development.
+         *
+         * <p>Applications targeting this or a later release will get these
+         * new changes in behavior:</p>
+         * <ul>
+         * <li> 2d drawing hardware acceleration is now turned on by default.
+         * You can use
+         * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
+         * to turn it off if needed, although this is strongly discouraged since
+         * it will result in poor performance on larger screen devices.
+         * </ul>
          */
         public static final int ICE_CREAM_SANDWICH = CUR_DEVELOPMENT;
     }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 5e99463..c9b6121 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -210,6 +210,21 @@
     NetworkStats getNetworkStatsUidDetail(int uid);
 
     /**
+     * Set quota for an interface.
+     */
+    void setInterfaceQuota(String iface, long quota);
+
+    /**
+     * Remove quota for an interface.
+     */
+    void removeInterfaceQuota(String iface);
+
+    /**
+     * Control network activity of a UID over interfaces with a quota limit.
+     */
+    void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
+
+    /**
      * Configures bandwidth throttling on an interface.
      */
     void setInterfaceThrottle(String iface, int rxKbps, int txKbps);
@@ -226,4 +241,6 @@
      */
     int getInterfaceTxThrottle(String iface);
 
+    void setBandwidthControlEnabled(boolean enabled);
+
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a17983a..21373ec 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -313,8 +313,8 @@
          */
         public void release(int flags) {
             synchronized (mToken) {
-                mHandler.removeCallbacks(mReleaser);
                 if (!mRefCounted || --mCount == 0) {
+                    mHandler.removeCallbacks(mReleaser);
                     try {
                         mService.releaseWakeLock(mToken, flags);
                     } catch (RemoteException e) {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index c2dc8ae..9302060 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -655,6 +655,26 @@
                 }
                 return _result;
             }
+
+            /*
+             * Returns the filesystem path of a mounted secure container.
+             */
+            public String getSecureContainerFilesystemPath(String id) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                String _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(id);
+                    mRemote.transact(Stub.TRANSACTION_getSecureContainerFilesystemPath, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readString();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
         }
 
         private static final String DESCRIPTOR = "IMountService";
@@ -719,6 +739,8 @@
 
         static final int TRANSACTION_getVolumeList = IBinder.FIRST_CALL_TRANSACTION + 29;
 
+        static final int TRANSACTION_getSecureContainerFilesystemPath = IBinder.FIRST_CALL_TRANSACTION + 30;
+
         /**
          * Cast an IBinder object into an IMountService interface, generating a
          * proxy if needed.
@@ -1031,6 +1053,15 @@
                     reply.writeParcelableArray(result, 0);
                     return true;
                 }
+                case TRANSACTION_getSecureContainerFilesystemPath: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String id;
+                    id = data.readString();
+                    String path = getSecureContainerFilesystemPath(id);
+                    reply.writeNoException();
+                    reply.writeString(path);
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1210,4 +1241,6 @@
      * Returns list of all mountable volumes.
      */
     public Parcelable[] getVolumeList() throws RemoteException;
+
+    public String getSecureContainerFilesystemPath(String id) throws RemoteException;
 }
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
index cde7dac..128b697 100644
--- a/core/java/android/pim/EventRecurrence.java
+++ b/core/java/android/pim/EventRecurrence.java
@@ -155,49 +155,6 @@
         }
     }
 
-    /**
-     * Parse an iCalendar/RFC2445 recur type according to Section 4.3.10.  The string is
-     * parsed twice, by the old and new parsers, and the results are compared.
-     * <p>
-     * TODO: this will go away, and what is now parse2() will simply become parse().
-     */
-    public void parse(String recur) {
-        InvalidFormatException newExcep = null;
-        try {
-            parse2(recur);
-        } catch (InvalidFormatException ife) {
-            newExcep = ife;
-        }
-
-        boolean oldThrew = false;
-        try {
-            EventRecurrence check = new EventRecurrence();
-            check.parseNative(recur);
-            if (newExcep == null) {
-                // Neither threw, check to see if results match.
-                if (!equals(check)) {
-                    throw new InvalidFormatException("Recurrence rule parse does not match [" +
-                            recur + "]");
-                }
-            }
-        } catch (InvalidFormatException ife) {
-            oldThrew = true;
-            if (newExcep == null) {
-                // Old threw, but new didn't.  Log a warning, but don't throw.
-                Log.d(TAG, "NOTE: old parser rejected [" + recur + "]: " + ife.getMessage());
-            }
-        }
-
-        if (newExcep != null) {
-            if (!oldThrew) {
-                // New threw, but old didn't.  Log a warning and throw the exception.
-                Log.d(TAG, "NOTE: new parser rejected [" + recur + "]: " + newExcep.getMessage());
-            }
-            throw newExcep;
-        }
-    }
-
-    native void parseNative(String recur);
 
     public void setStartDate(Time date) {
         startDate = date;
@@ -456,6 +413,19 @@
         return true;
     }
 
+    /**
+     * Determines whether this rule specifies a simple monthly rule by weekday, such as
+     * "FREQ=MONTHLY;BYDAY=3TU" (the 3rd Tuesday of every month).
+     * <p>
+     * Negative days, e.g. "FREQ=MONTHLY;BYDAY=-1TU" (the last Tuesday of every month),
+     * will cause "false" to be returned.
+     * <p>
+     * Rules that fire every week, such as "FREQ=MONTHLY;BYDAY=TU" (every Tuesday of every
+     * month) will cause "false" to be returned.  (Note these are usually expressed as
+     * WEEKLY rules, and hence are uncommon.)
+     *
+     * @return true if this rule is of the appropriate form
+     */
     public boolean repeatsMonthlyOnDayCount() {
         if (this.freq != MONTHLY) {
             return false;
@@ -465,6 +435,10 @@
             return false;
         }
 
+        if (bydayNum[0] <= 0) {
+            return false;
+        }
+
         return true;
     }
 
@@ -549,7 +523,7 @@
      *
      * @param recur The recurrence rule to parse (in un-folded form).
      */
-    void parse2(String recur) {
+    public void parse(String recur) {
         /*
          * From RFC 2445 section 4.3.10:
          *
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 4368e31..3971045 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -17,6 +17,8 @@
 package android.provider;
 
 
+import com.android.internal.util.ArrayUtils;
+
 import android.accounts.Account;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -38,6 +40,8 @@
 import android.text.format.Time;
 import android.util.Log;
 
+import java.util.Arrays;
+
 /**
  * <p>
  * The contract between the calendar provider and applications. Contains
@@ -94,19 +98,19 @@
      * Broadcast Action: This is the intent that gets fired when an alarm
      * notification needs to be posted for a reminder.
      */
-    public static final String EVENT_REMINDER_ACTION = "android.intent.action.EVENT_REMINDER";
+    public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
 
     /**
      * Intent Extras key: The start time of an event or an instance of a
      * recurring event. (milliseconds since epoch)
      */
-    public static final String EVENT_BEGIN_TIME = "beginTime";
+    public static final String EXTRA_EVENT_BEGIN_TIME = "beginTime";
 
     /**
      * Intent Extras key: The end time of an event or an instance of a recurring
      * event. (milliseconds since epoch)
      */
-    public static final String EVENT_END_TIME = "endTime";
+    public static final String EXTRA_EVENT_END_TIME = "endTime";
 
     /**
      * This authority is used for writing to or querying from the calendar
@@ -279,7 +283,7 @@
     /**
      * Columns specific to the Calendars Uri that other Uris can query.
      */
-    protected interface CalendarsColumns {
+    protected interface CalendarColumns {
         /**
          * The color of the calendar
          * <P>Type: INTEGER (color value)</P>
@@ -385,7 +389,7 @@
      * Class that represents a Calendar Entity. There is one entry per calendar.
      * This is a helper class to make batch operations easier.
      */
-    public static class CalendarsEntity implements BaseColumns, SyncColumns, CalendarsColumns {
+    public static class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
 
         /**
          * The default Uri used when creating a new calendar EntityIterator.
@@ -567,7 +571,7 @@
      * <li>{@link #CAL_SYNC10}</li>
      * </ul>
      */
-    public static class Calendars implements BaseColumns, SyncColumns, CalendarsColumns {
+    public static class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
         private static final String WHERE_DELETE_FOR_ACCOUNT = Calendars.ACCOUNT_NAME + "=?"
                 + " AND "
                 + Calendars.ACCOUNT_TYPE + "=?";
@@ -592,37 +596,6 @@
         }
 
         /**
-         * Convenience method perform a delete on the Calendar provider. This is
-         * a blocking call and should not be used on the UI thread.
-         *
-         * @param cr the ContentResolver
-         * @param selection A filter to apply to rows before deleting, formatted
-         *            as an SQL WHERE clause (excluding the WHERE itself).
-         * @param selectionArgs Fill in the '?'s in the selection
-         * @return the count of rows that were deleted
-         */
-        public static int delete(ContentResolver cr, String selection, String[] selectionArgs)
-        {
-            return cr.delete(CONTENT_URI, selection, selectionArgs);
-        }
-
-        /**
-         * Convenience method to delete all calendars that match the account.
-         * This is a blocking call and should not be used on the UI thread.
-         *
-         * @param cr the ContentResolver
-         * @param account the account whose calendars and events should be
-         *            deleted
-         * @return the count of calendar rows that were deleted
-         */
-        public static int deleteCalendarsForAccount(ContentResolver cr, Account account) {
-            // delete all calendars that match this account
-            return CalendarContract.Calendars.delete(cr,
-                    WHERE_DELETE_FOR_ACCOUNT,
-                    new String[] { account.name, account.type });
-        }
-
-        /**
          * The content:// style URL for accessing Calendars
          */
         @SuppressWarnings("hiding")
@@ -764,7 +737,7 @@
         /**
          * the projection used by the attendees query
          */
-        public static final String[] PROJECTION = new String[] {
+        private static final String[] PROJECTION = new String[] {
                 _ID, ATTENDEE_NAME, ATTENDEE_EMAIL, ATTENDEE_RELATIONSHIP, ATTENDEE_STATUS,};
         private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
 
@@ -1444,7 +1417,7 @@
      * views into other tables and cannot be changed through the Events table.
      */
     public static final class Events implements BaseColumns, SyncColumns, EventsColumns,
-            CalendarsColumns {
+            CalendarColumns {
 
         /**
          * Queries all events with the given projection. This is a blocking call
@@ -1556,9 +1529,12 @@
      * days and minutes. The instances table is not writable and only provides a
      * way to query event occurrences.
      */
-    public static final class Instances implements BaseColumns, EventsColumns, CalendarsColumns {
+    public static final class Instances implements BaseColumns, EventsColumns, CalendarColumns {
 
-        private static final String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=1";
+        private static final String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=?";
+        private static final String[] WHERE_CALENDARS_ARGS = {
+            "1"
+        };
 
         /**
          * Performs a query to return all visible instances in the given range.
@@ -1581,7 +1557,7 @@
             ContentUris.appendId(builder, begin);
             ContentUris.appendId(builder, end);
             return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED,
-                         null, DEFAULT_SORT_ORDER);
+                    WHERE_CALENDARS_ARGS, DEFAULT_SORT_ORDER);
         }
 
         /**
@@ -1610,79 +1586,8 @@
             ContentUris.appendId(builder, begin);
             ContentUris.appendId(builder, end);
             builder = builder.appendPath(searchQuery);
-            return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED, null,
-                    DEFAULT_SORT_ORDER);
-        }
-
-        /**
-         * Performs a query to return all visible instances in the given range
-         * that match the given selection. This is a blocking function and
-         * should not be done on the UI thread. This will cause an expansion of
-         * recurring events to fill this time range if they are not already
-         * expanded and will slow down for larger time ranges with many
-         * recurring events.
-         *
-         * @param cr The ContentResolver to use for the query
-         * @param projection The columns to return
-         * @param begin The start of the time range to query in UTC millis since
-         *            epoch
-         * @param end The end of the time range to query in UTC millis since
-         *            epoch
-         * @param selection Filter on the query as an SQL WHERE statement
-         * @param selectionArgs Args to replace any '?'s in the selection
-         * @param orderBy How to order the rows as an SQL ORDER BY statement
-         * @return A Cursor of instances matching the selection
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection, long begin,
-                long end, String selection, String[] selectionArgs, String orderBy) {
-            Uri.Builder builder = CONTENT_URI.buildUpon();
-            ContentUris.appendId(builder, begin);
-            ContentUris.appendId(builder, end);
-            if (TextUtils.isEmpty(selection)) {
-                selection = WHERE_CALENDARS_SELECTED;
-            } else {
-                selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
-            }
-            return cr.query(builder.build(), projection, selection, selectionArgs,
-                    orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-        }
-
-        /**
-         * Performs a query to return all visible instances in the given range
-         * that match the given selection. This is a blocking function and
-         * should not be done on the UI thread. This will cause an expansion of
-         * recurring events to fill this time range if they are not already
-         * expanded and will slow down for larger time ranges with many
-         * recurring events.
-         *
-         * @param cr The ContentResolver to use for the query
-         * @param projection The columns to return
-         * @param begin The start of the time range to query in UTC millis since
-         *            epoch
-         * @param end The end of the time range to query in UTC millis since
-         *            epoch
-         * @param searchQuery A string of space separated search terms. Segments
-         *            enclosed by double quotes will be treated as a single
-         *            term.
-         * @param selection Filter on the query as an SQL WHERE statement
-         * @param selectionArgs Args to replace any '?'s in the selection
-         * @param orderBy How to order the rows as an SQL ORDER BY statement
-         * @return A Cursor of instances matching the selection
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection, long begin,
-                long end, String searchQuery, String selection, String[] selectionArgs,
-                String orderBy) {
-            Uri.Builder builder = CONTENT_SEARCH_URI.buildUpon();
-            ContentUris.appendId(builder, begin);
-            ContentUris.appendId(builder, end);
-            builder = builder.appendPath(searchQuery);
-            if (TextUtils.isEmpty(selection)) {
-                selection = WHERE_CALENDARS_SELECTED;
-            } else {
-                selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
-            }
-            return cr.query(builder.build(), projection, selection, selectionArgs,
-                    orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+            return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED,
+                    WHERE_CALENDARS_ARGS, DEFAULT_SORT_ORDER);
         }
 
         /**
@@ -1790,7 +1695,6 @@
          */
         public static final Uri URI =
                 Uri.parse("content://" + AUTHORITY + "/properties");
-        public static final String[] POJECTION = { KEY, VALUE };
 
         /**
          * If updating a property, this must be provided as the selection. All
@@ -1910,7 +1814,9 @@
         /**
          * The projection used by the EventDays query.
          */
-        public static final String[] PROJECTION = { STARTDAY, ENDDAY };
+        private static final String[] PROJECTION = {
+                STARTDAY, ENDDAY
+        };
         private static final String SELECTION = "selected=1";
 
         /**
@@ -1994,7 +1900,7 @@
         /**
          * The projection used by the reminders query.
          */
-        public static final String[] PROJECTION = new String[] {
+        private static final String[] PROJECTION = new String[] {
                 _ID, MINUTES, METHOD,};
         @SuppressWarnings("hiding")
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/reminders");
@@ -2089,7 +1995,7 @@
     /**
      * Fields and helpers for accessing calendar alerts information. These
      * fields are for tracking which alerts have been fired. Scheduled alarms
-     * will generate an intent using {@link #EVENT_REMINDER_ACTION}. Apps that
+     * will generate an intent using {@link #ACTION_EVENT_REMINDER}. Apps that
      * receive this action may update the {@link #STATE} for the reminder when
      * they have finished handling it. Apps that have their notifications
      * disabled should not modify the table to ensure that they do not conflict
@@ -2098,7 +2004,7 @@
      * state of a reminder.
      */
     public static final class CalendarAlerts implements BaseColumns,
-            CalendarAlertsColumns, EventsColumns, CalendarsColumns {
+            CalendarAlertsColumns, EventsColumns, CalendarColumns {
 
         /**
          * @hide
@@ -2271,7 +2177,7 @@
          * keep scheduled reminders up to date but apps may use this to
          * implement snooze functionality without modifying the reminders table.
          * Scheduled alarms will generate an intent using
-         * {@link #EVENT_REMINDER_ACTION}.
+         * {@link #ACTION_EVENT_REMINDER}.
          *
          * @param context A context for referencing system resources
          * @param manager The AlarmManager to use or null
@@ -2290,7 +2196,7 @@
                 manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
             }
 
-            Intent intent = new Intent(EVENT_REMINDER_ACTION);
+            Intent intent = new Intent(ACTION_EVENT_REMINDER);
             intent.setData(ContentUris.withAppendedId(CalendarContract.CONTENT_URI, alarmTime));
             intent.putExtra(ALARM_TIME, alarmTime);
             PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 02faf49..39c6f57 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -24,6 +24,8 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.DataUsageFeedback;
 import android.text.TextUtils;
 
 /**
@@ -55,6 +57,29 @@
                 Uri.parse("content://call_log/calls/filter");
 
         /**
+         * An optional URI parameter which instructs the provider to allow the operation to be
+         * applied to voicemail records as well.
+         * <p>
+         * TYPE: Boolean
+         * <p>
+         * Using this parameter with a value of {@code true} will result in a security error if the
+         * calling package does not have appropriate permissions to access voicemails.
+         *
+         * @hide
+         */
+        public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
+
+        /**
+         * Content uri with {@link #ALLOW_VOICEMAILS_PARAM_KEY} set. This can directly be used to
+         * access call log entries that includes voicemail records.
+         *
+         * @hide
+         */
+        public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
+                .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
+                .build();
+
+        /**
          * The default sort order for this table
          */
         public static final String DEFAULT_SORT_ORDER = "date DESC";
@@ -204,7 +229,44 @@
             }
 
             if ((ci != null) && (ci.person_id > 0)) {
-                ContactsContract.Contacts.markAsContacted(resolver, ci.person_id);
+                // Update usage information for the number associated with the contact ID.
+                // We need to use both the number and the ID for obtaining a data ID since other
+                // contacts may have the same number.
+
+                final Cursor cursor;
+
+                // We should prefer normalized one (probably coming from
+                // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
+                if (ci.normalizedNumber != null) {
+                    final String normalizedPhoneNumber = ci.normalizedNumber;
+                    cursor = resolver.query(Phone.CONTENT_URI,
+                            new String[] { Phone._ID },
+                            Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
+                            new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber},
+                            null);
+                } else {
+                    final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
+                    cursor = resolver.query(Phone.CONTENT_URI,
+                            new String[] { Phone._ID },
+                            Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?",
+                            new String[] { String.valueOf(ci.person_id), phoneNumber},
+                            null);
+                }
+
+                if (cursor != null) {
+                    try {
+                        if (cursor.getCount() > 0 && cursor.moveToFirst()) {
+                            final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
+                                    .appendPath(cursor.getString(0))
+                                    .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+                                                DataUsageFeedback.USAGE_TYPE_CALL)
+                                    .build();
+                            resolver.update(feedbackUri, new ContentValues(), null, null);
+                        }
+                    } finally {
+                        cursor.close();
+                    }
+                }
             }
 
             Uri result = resolver.insert(CONTENT_URI, values);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b5a11ab..ad71061 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -123,14 +123,16 @@
 
     /**
      * An optional URI parameter for selection queries that instructs the
-     * provider to include the user's personal profile contact entry (if any)
-     * in the contact results.  If present, the user's profile will always be
-     * the first entry returned.  The default value is false.
+     * provider to allow the user's personal profile contact entry (if any)
+     * to appear in a list of contact results.  It is only useful when issuing
+     * a query that may retrieve more than one contact.  If present, the user's
+     * profile will always be the first entry returned.  The default value is
+     * false.
      *
      * Specifying this parameter will result in a security error if the calling
      * application does not have android.permission.READ_PROFILE permission.
      */
-    public static final String INCLUDE_PROFILE = "include_profile";
+    public static final String ALLOW_PROFILE = "allow_profile";
 
     /**
      * A query parameter key used to specify the package that is requesting a query.
@@ -172,6 +174,15 @@
      */
     public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
 
+    /**
+     * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and
+     * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to
+     * return only phone-related results. For example, frequently contacted person list should
+     * include persons contacted via phone (not email, sms, etc.)
+     *
+     * @hide
+     */
+    public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
 
     /**
      * @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 19e9a67..65babc2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -20,6 +20,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -3490,6 +3491,18 @@
                 "sms_outgoing_check_max_count";
 
         /**
+         * The global search provider chosen by the user (if multiple global
+         * search providers are installed). This will be the provider returned
+         * by {@link SearchManager#getGlobalSearchActivity()} if it's still
+         * installed. This setting is stored as a flattened component name as
+         * per {@link ComponentName#flattenToString()}.
+         *
+         * @hide
+         */
+        public static final String SEARCH_GLOBAL_SEARCH_ACTIVITY =
+                "search_global_search_activity";
+
+        /**
          * The number of promoted sources in GlobalSearch.
          * @hide
          */
@@ -3804,6 +3817,8 @@
                 "dream_timeout";
 
         /** {@hide} */
+        public static final String NETSTATS_ENABLED = "netstats_enabled";
+        /** {@hide} */
         public static final String NETSTATS_POLL_INTERVAL = "netstats_poll_interval";
         /** {@hide} */
         public static final String NETSTATS_PERSIST_THRESHOLD = "netstats_persist_threshold";
diff --git a/core/java/android/provider/SyncConstValue.java b/core/java/android/provider/SyncConstValue.java
index 2fcf315..027aed1 100644
--- a/core/java/android/provider/SyncConstValue.java
+++ b/core/java/android/provider/SyncConstValue.java
@@ -18,7 +18,7 @@
 
 /**
  * Columns for tables that are synced to a server.
- * @deprecated
+ * @deprecated Do not use.
  * @hide
  */
 public interface SyncConstValue
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index ae41876..ab0cb50 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -63,14 +63,13 @@
     // TODO: Move ACTION_NEW_VOICEMAIL to the Intent class.
     /** Broadcast intent when a new voicemail record is inserted. */
     public static final String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+
     /**
      * Extra included in {@value Intent#ACTION_PROVIDER_CHANGED} and
-     * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate the package
-     * that caused the change in content provider.
-     * <p>Receivers of the broadcast can use this field to determine if this is
-     * a self change.
+     * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate if the receiving
+     * package made this change.
      */
-    public static final String EXTRA_CHANGED_BY = "com.android.voicemail.extra.CHANGED_BY";
+    public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
 
     /** The mime type for a collection of voicemails. */
     public static final String DIR_TYPE =
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
index 39c3c88..76e7885 100644
--- a/core/java/android/server/BluetoothBondState.java
+++ b/core/java/android/server/BluetoothBondState.java
@@ -79,7 +79,6 @@
         mService = service;
         mBluetoothInputProfileHandler =
             BluetoothInputProfileHandler.getInstance(mContext, mService);
-        getProfileProxy();
     }
 
     synchronized void setPendingOutgoingBonding(String address) {
@@ -90,7 +89,12 @@
         return mPendingOutgoingBonding;
     }
 
-    public synchronized void loadBondState() {
+    public synchronized void initBondState() {
+        getProfileProxy();
+        loadBondState();
+    }
+
+    private void loadBondState() {
         if (mService.getBluetoothStateInternal() !=
                 BluetoothAdapter.STATE_TURNING_ON) {
             return;
diff --git a/core/java/android/server/BluetoothDeviceProperties.java b/core/java/android/server/BluetoothDeviceProperties.java
index 3dc53d7..fe3ef79 100644
--- a/core/java/android/server/BluetoothDeviceProperties.java
+++ b/core/java/android/server/BluetoothDeviceProperties.java
@@ -35,43 +35,45 @@
         mService = service;
     }
 
-    synchronized Map<String, String> addProperties(String address,
-            String[] properties) {
+    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 = mPropertiesMap.get(address);
-        if (propertyValues == null) {
-            propertyValues = new HashMap<String, String>();
-        }
+        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 "
+            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(",");
+                    continue;
                 }
-                if (len > 0) {
-                    newValue = str.toString();
+                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];
                 }
-            } else {
-                newValue = properties[++i];
-            }
 
-            propertyValues.put(name, newValue);
+                propertyValues.put(name, newValue);
+            }
+            mPropertiesMap.put(address, propertyValues);
         }
-        mPropertiesMap.put(address, propertyValues);
 
         // We have added a new remote device or updated its properties.
         // Also update the serviceChannel cache.
@@ -79,46 +81,56 @@
         return propertyValues;
     }
 
-    synchronized void setProperty(String address, String name, String value) {
-        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);
+    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);
+            }
         }
     }
 
-    synchronized boolean isInCache(String address) {
-        return (mPropertiesMap.get(address) != null);
+    boolean isInCache(String address) {
+        synchronized (mPropertiesMap) {
+            return (mPropertiesMap.get(address) != null);
+        }
     }
 
-    synchronized boolean isEmpty() {
-        return mPropertiesMap.isEmpty();
+    boolean isEmpty() {
+        synchronized (mPropertiesMap) {
+            return mPropertiesMap.isEmpty();
+        }
     }
 
-    synchronized Set<String> keySet() {
-        return mPropertiesMap.keySet();
+    Set<String> keySet() {
+        synchronized (mPropertiesMap) {
+            return mPropertiesMap.keySet();
+        }
     }
 
-    synchronized String getProperty(String address, String property) {
-        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);
+    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;
     }
 
-    synchronized Map<String, String> updateCache(String address) {
+    Map<String, String> updateCache(String address) {
         String[] propValues = mService.getRemoteDeviceProperties(address);
         if (propValues != null) {
             return addProperties(address, propValues);
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index e72aaa7..a220007 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -989,6 +989,33 @@
                                                       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 void onRestartRequired() {
         if (mBluetoothService.isEnabled()) {
             Log.e(TAG, "*** A serious error occurred (did bluetoothd crash?) - " +
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
new file mode 100644
index 0000000..7f862e0
--- /dev/null
+++ b/core/java/android/server/BluetoothHealthProfileHandler.java
@@ -0,0 +1,600 @@
+/*
+ * 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.BluetoothHealth;
+import android.bluetooth.BluetoothInputDevice;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * 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";
+    /*STOPSHIP*/
+    private static final boolean DBG = true;
+
+    private static BluetoothHealthProfileHandler sInstance;
+    private Context mContext;
+    private BluetoothService mBluetoothService;
+    private ArrayList<HealthChannel> mHealthChannels;
+    private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
+    private HashMap <BluetoothDevice, Integer> mHealthDevices;
+
+    private static final int MESSAGE_REGISTER_APPLICATION = 0;
+    private static final int MESSAGE_UNREGISTER_APPLICATION = 1;
+    private static final int MESSAGE_CONNECT_CHANNEL = 2;
+
+    class HealthChannel {
+        private ParcelFileDescriptor mChannelFd;
+        private boolean mMainChannel;
+        private String mChannelPath;
+        private BluetoothDevice mDevice;
+        private BluetoothHealthAppConfiguration mConfig;
+        private int mState;
+        private int mChannelType;
+
+        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;
+        }
+    }
+
+    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.APPLICATION_REGISTRATION_FAILURE);
+                } else {
+                    mHealthAppConfigs.put(registerApp, path);
+                    callHealthApplicationStatusCallback(registerApp,
+                            BluetoothHealth.APPLICATION_REGISTRATION_SUCCESS);
+                }
+
+                break;
+            case MESSAGE_UNREGISTER_APPLICATION:
+                BluetoothHealthAppConfiguration unregisterApp =
+                    (BluetoothHealthAppConfiguration) msg.obj;
+                boolean result = mBluetoothService.unregisterHealthApplicationNative(
+                        mHealthAppConfigs.get(unregisterApp));
+                if (result) {
+                    callHealthApplicationStatusCallback(unregisterApp,
+                            BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS);
+                } else {
+                    callHealthApplicationStatusCallback(unregisterApp,
+                            BluetoothHealth.APPLICATION_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)) {
+                    int prevState = chan.mState;
+                    int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+                    callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null);
+                    mHealthChannels.remove(chan);
+                }
+            }
+        }
+    };
+
+    private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
+        mContext = context;
+        mBluetoothService = service;
+        mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
+        mHealthChannels = new ArrayList<HealthChannel>();
+        mHealthDevices = new HashMap<BluetoothDevice, Integer>();
+    }
+
+    static synchronized BluetoothHealthProfileHandler getInstance(Context context,
+            BluetoothService service) {
+        if (sInstance == null) sInstance = new BluetoothHealthProfileHandler(context, service);
+        return sInstance;
+    }
+
+    boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) {
+        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION);
+        msg.obj = config;
+        mHandler.sendMessage(msg);
+        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);
+
+        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;
+        }
+    }
+
+    boolean disconnectChannel(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+        HealthChannel chan = findChannelByFd(device, config, fd);
+        if (chan == null) return false;
+
+        String deviceObjectPath =
+                mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        if (mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
+            int prevState = chan.mState;
+            chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
+            callHealthChannelCallback(config, device, prevState, chan.mState,
+                    chan.mChannelFd);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private HealthChannel findChannelByFd(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+        for (HealthChannel chan : mHealthChannels) {
+            if (chan.mChannelFd.equals(fd) && chan.mDevice.equals(device) &&
+                    chan.mConfig.equals(config)) return chan;
+        }
+        return null;
+    }
+
+    private HealthChannel findChannelByPath(BluetoothDevice device,
+            BluetoothHealthAppConfiguration config, String path) {
+        for (HealthChannel chan : mHealthChannels) {
+            if (chan.mChannelPath.equals(path) && chan.mDevice.equals(device) &&
+                    chan.mConfig.equals(config)) 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) return chan.mChannelFd;
+
+        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, config, mainChannelPath);
+        if (chan == null) {
+            errorLog("Main Channel present but we don't have any account of it:" +
+                    device +":" + config);
+            return null;
+        }
+        chan.mMainChannel = true;
+        return chan.mChannelFd;
+    }
+
+    /*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, config, channelPath);
+            if (chan == null) {
+                errorLog("Health Channel is not present:" + channelPath);
+            } else {
+                chan.mMainChannel = true;
+            }
+        }
+    }
+
+    private BluetoothHealthAppConfiguration findHealthApplication(
+            BluetoothDevice device, String channelPath) {
+        BluetoothHealthAppConfiguration config = null;
+        String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
+
+        if (configPath == null) {
+            errorLog("No associated application for Health Channel:" + channelPath);
+            return null;
+        } else {
+            for (Entry<BluetoothHealthAppConfiguration, String> e :
+                    mHealthAppConfigs.entrySet()) {
+                if (e.getValue().equals(configPath)) {
+                    config = e.getKey();
+                }
+            }
+            if (config == null) {
+                errorLog("No associated application for application path:" + configPath);
+                return null;
+            }
+        }
+        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 = findHealthApplication(device,
+                channelPath);
+        int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+        ParcelFileDescriptor fd;
+        HealthChannel channel;
+
+        if (config != null) {
+             if (exists) {
+                 fd = mBluetoothService.getChannelFdNative(channelPath);
+
+                 if (fd == null) {
+                     errorLog("Error obtaining fd for channel:" + channelPath);
+                     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 = findConnectingChannel(device, config);
+                 if (channel != null) {
+                    channel.mChannelFd = fd;
+                    channel.mMainChannel = mainChannel;
+                    channel.mChannelPath = channelPath;
+                    prevState = channel.mState;
+                 } else {
+                    channel = new HealthChannel(device, config, fd, mainChannel,
+                            channelPath);
+                    mHealthChannels.add(channel);
+                    prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+                 }
+                 state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
+             } else {
+                 channel = findChannelByPath(device, config, channelPath);
+                 if (channel == null) {
+                     errorLog("Channel not found:" + config + ":" + channelPath);
+                     return;
+                 }
+
+                 fd = channel.mChannelFd;
+                 // CLOSE FD
+                 mBluetoothService.releaseChannelFdNative(channel.mChannelPath);
+                 mHealthChannels.remove(channel);
+
+                 prevState = channel.mState;
+                 state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+             }
+             channel.mState = state;
+             callHealthChannelCallback(config, device, prevState, state, fd);
+        }
+    }
+
+    private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
+            BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd) {
+        broadcastHealthDeviceStateChange(device, prevState, state);
+
+        debugLog("Health Device Callback: " + device + " State Change: "
+                + prevState + "->" + state);
+        try {
+            config.getCallback().onHealthChannelStateChange(config, device, prevState,
+                    state, fd);
+        } catch (RemoteException e) {
+            errorLog("Error while making health channel state change callback: " + e);
+        }
+    }
+
+    private void callHealthApplicationStatusCallback(
+            BluetoothHealthAppConfiguration config, int status) {
+        debugLog("Health Device Application: " + config + " State Change: status:"
+                + status);
+        try {
+            config.getCallback().onHealthAppConfigurationStatusChange(config, status);
+        } catch (RemoteException e) {
+            errorLog("Error while making health app registration state change callback: " + 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);
+                    }
+                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, prevDeviceState, newDeviceState);
+    }
+
+    /**
+     * 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/BluetoothService.java b/core/java/android/server/BluetoothService.java
old mode 100755
new mode 100644
index a4588ae..b5ae298
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -31,6 +31,7 @@
 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;
@@ -49,6 +50,7 @@
 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;
@@ -148,6 +150,7 @@
     private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
     private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
     private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
+    private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler;
 
     private static class RemoteService {
         public String address;
@@ -220,6 +223,7 @@
         mContext.registerReceiver(mReceiver, filter);
         mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
         mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
+        mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
     }
 
     public static synchronized String readDockBluetoothAddress() {
@@ -566,7 +570,7 @@
 
                 mIsDiscovering = false;
                 mBondState.readAutoPairingData();
-                mBondState.loadBondState();
+                mBondState.initBondState();
                 initProfileState();
 
                 // This should be the last step of the the enable thread.
@@ -2077,6 +2081,106 @@
         }
     }
 
+    /**** Handlers for Health Device Profile ****/
+    // TODO: All these need to be converted to a state machine.
+
+    public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                "Need BLUETOOTH permission");
+        synchronized (mBluetoothHealthProfileHandler) {
+                return mBluetoothHealthProfileHandler.registerAppConfiguration(config);
+        }
+    }
+
+    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, ParcelFileDescriptor fd) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                "Need BLUETOOTH permission");
+        synchronized (mBluetoothHealthProfileHandler) {
+            return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd);
+        }
+    }
+
+    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);
+        }
+    }
+
+    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);
+        }
+    }
+
     public boolean connectHeadset(String address) {
         if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
 
@@ -2375,4 +2479,16 @@
 
     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);
+    native boolean destroyChannelNative(String devicePath, String channelpath);
+    native String getMainChannelNative(String path);
+    native String getChannelApplicationNative(String channelPath);
+    native ParcelFileDescriptor getChannelFdNative(String channelPath);
+    native boolean releaseChannelFdNative(String channelPath);
 }
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 3826a01..79ade260 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -23,10 +23,14 @@
 import android.app.SearchableInfo;
 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.pm.ResolveInfo;
+import android.database.ContentObserver;
 import android.os.Process;
+import android.provider.Settings;
 import android.util.Log;
 
 import java.util.List;
@@ -46,6 +50,8 @@
     // This field is initialized lazily in getSearchables(), and then never modified.
     private Searchables mSearchables;
 
+    private ContentObserver mGlobalSearchObserver;
+
     /**
      * Initializes the Search Manager service in the provided system context.
      * Only one instance of this object should be created!
@@ -56,6 +62,8 @@
         mContext = context;
         mContext.registerReceiver(new BootCompletedReceiver(),
                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+        mGlobalSearchObserver = new GlobalSearchProviderObserver(
+                mContext.getContentResolver());
     }
 
     private synchronized Searchables getSearchables() {
@@ -100,6 +108,28 @@
         }
     }
 
+    class GlobalSearchProviderObserver extends ContentObserver {
+        private final ContentResolver mResolver;
+
+        public GlobalSearchProviderObserver(ContentResolver resolver) {
+            super(null);
+            mResolver = resolver;
+            mResolver.registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY),
+                    false /* notifyDescendants */,
+                    this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            getSearchables().buildSearchableList();
+            Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            mContext.sendBroadcast(intent);
+        }
+
+    }
+
     //
     // Searchable activities API
     //
@@ -126,6 +156,10 @@
         return getSearchables().getSearchablesInGlobalSearchList();
     }
 
+    public List<ResolveInfo> getGlobalSearchActivities() {
+        return getSearchables().getGlobalSearchActivities();
+    }
+
     /**
      * Gets the name of the global search activity.
      */
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index 279c17d..f24d52f 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,19 +16,23 @@
 
 package android.server.search;
 
-import android.Manifest;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 
@@ -50,7 +54,10 @@
     private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
     private ArrayList<SearchableInfo> mSearchablesList = null;
     private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
-    private ComponentName mGlobalSearchActivity = null;
+    // Contains all installed activities that handle the global search
+    // intent.
+    private List<ResolveInfo> mGlobalSearchActivities;
+    private ComponentName mCurrentGlobalSearchActivity = null;
     private ComponentName mWebSearchActivity = null;
 
     public static String GOOGLE_SEARCH_COMPONENT_NAME =
@@ -224,8 +231,11 @@
             }
         }
 
+        List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
+
         // Find the global search activity
-        ComponentName newGlobalSearchActivity = findGlobalSearchActivity();
+        ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
+                newGlobalSearchActivities);
 
         // Find the web search activity
         ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
@@ -235,38 +245,124 @@
             mSearchablesMap = newSearchablesMap;
             mSearchablesList = newSearchablesList;
             mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
-            mGlobalSearchActivity = newGlobalSearchActivity;
+            mGlobalSearchActivities = newGlobalSearchActivities;
+            mCurrentGlobalSearchActivity = newGlobalSearchActivity;
             mWebSearchActivity = newWebSearchActivity;
         }
     }
-
     /**
-     * Finds the global search activity.
+     * Returns a sorted list of installed search providers as per
+     * the following heuristics:
      *
-     * This is currently implemented by returning the first activity that handles
-     * the GLOBAL_SEARCH intent and has the GLOBAL_SEARCH permission. If we allow
-     * more than one global search activity to be installed, this code must be changed.
+     * (a) System apps are given priority over non system apps.
+     * (b) Among system apps and non system apps, the relative ordering
+     * is defined by their declared priority.
      */
-    private ComponentName findGlobalSearchActivity() {
+    private List<ResolveInfo> findGlobalSearchActivities() {
+        // 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);
-        int count = activities == null ? 0 : activities.size();
-        for (int i = 0; i < count; i++) {
-            ActivityInfo ai = activities.get(i).activityInfo;
-            if (pm.checkPermission(Manifest.permission.GLOBAL_SEARCH,
-                    ai.packageName) == PackageManager.PERMISSION_GRANTED) {
-                return new ComponentName(ai.packageName, ai.name);
-            } else {
-                Log.w(LOG_TAG, "Package " + ai.packageName + " wants to handle GLOBAL_SEARCH, "
-                        + "but does not have the GLOBAL_SEARCH permission.");
+
+        if (activities != null && !activities.isEmpty()) {
+            // Step 2: Rank matching activities according to our heuristics.
+            Collections.sort(activities, GLOBAL_SEARCH_RANKER);
+        }
+
+        return activities;
+    }
+
+    /**
+     * Finds the global search activity.
+     */
+    private ComponentName findGlobalSearchActivity(List<ResolveInfo> installed) {
+        // Fetch the global search provider from the system settings,
+        // and if it's still installed, return it.
+        final String searchProviderSetting = getGlobalSearchProviderSetting();
+        if (!TextUtils.isEmpty(searchProviderSetting)) {
+            final ComponentName globalSearchComponent = ComponentName.unflattenFromString(
+                    searchProviderSetting);
+            if (globalSearchComponent != null && isInstalled(globalSearchComponent)) {
+                return globalSearchComponent;
             }
         }
+
+        return getDefaultGlobalSearchProvider(installed);
+    }
+
+    /**
+     * Checks whether the global search provider with a given
+     * component name is installed on the system or not. This deals with
+     * cases such as the removal of an installed provider.
+     */
+    private boolean isInstalled(ComponentName globalSearch) {
+        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);
+
+        if (activities != null && !activities.isEmpty()) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static final Comparator<ResolveInfo> GLOBAL_SEARCH_RANKER =
+            new Comparator<ResolveInfo>() {
+        @Override
+        public int compare(ResolveInfo lhs, ResolveInfo rhs) {
+            if (lhs == rhs) {
+                return 0;
+            }
+            boolean lhsSystem = isSystemApp(lhs);
+            boolean rhsSystem = isSystemApp(rhs);
+
+            if (lhsSystem && !rhsSystem) {
+                return -1;
+            } else if (rhsSystem && !lhsSystem) {
+                return 1;
+            } else {
+                // Either both system engines, or both non system
+                // engines.
+                //
+                // Note, this isn't a typo. Higher priority numbers imply
+                // higher priority, but are "lower" in the sort order.
+                return rhs.priority - lhs.priority;
+            }
+        }
+    };
+
+    /**
+     * @return true iff. the resolve info corresponds to a system application.
+     */
+    private static final boolean isSystemApp(ResolveInfo res) {
+        return (res.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    /**
+     * Returns the highest ranked search provider as per the
+     * ranking defined in {@link #getGlobalSearchActivities()}.
+     */
+    private ComponentName getDefaultGlobalSearchProvider(List<ResolveInfo> providerList) {
+        if (providerList != null && !providerList.isEmpty()) {
+            ActivityInfo ai = providerList.get(0).activityInfo;
+            return new ComponentName(ai.packageName, ai.name);
+        }
+
         Log.w(LOG_TAG, "No global search activity found");
         return null;
     }
 
+    private String getGlobalSearchProviderSetting() {
+        return Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY);
+    }
+
     /**
      * Finds the web search activity.
      *
@@ -281,9 +377,9 @@
         PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
                 pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-        int count = activities == null ? 0 : activities.size();
-        for (int i = 0; i < count; i++) {
-            ActivityInfo ai = activities.get(i).activityInfo;
+
+        if (activities != null && !activities.isEmpty()) {
+            ActivityInfo ai = activities.get(0).activityInfo;
             // TODO: do some sanity checks here?
             return new ComponentName(ai.packageName, ai.name);
         }
@@ -307,10 +403,17 @@
     }
 
     /**
+     * Returns a list of activities that handle the global search intent.
+     */
+    public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() {
+        return new ArrayList<ResolveInfo>(mGlobalSearchActivities);
+    }
+
+    /**
      * Gets the name of the global search activity.
      */
     public synchronized ComponentName getGlobalSearchActivity() {
-        return mGlobalSearchActivity;
+        return mCurrentGlobalSearchActivity;
     }
 
     /**
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 5ee33e1..8e4725f 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -442,7 +442,7 @@
     private final Map<String, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
     private final TtsEngines mEnginesHelper;
-    private String mCurrentEngine = null;
+    private volatile String mCurrentEngine = null;
 
     /**
      * The constructor for the TextToSpeech class, using the default TTS engine.
@@ -573,6 +573,7 @@
                 service.setCallback(getPackageName(), null);
                 service.stop(getPackageName());
                 mServiceConnection.disconnect();
+                mCurrentEngine = null;
                 return null;
             }
         }, null, "shutdown");
@@ -869,6 +870,14 @@
     }
 
     /**
+     * @return the engine currently in use by this TextToSpeech instance.
+     * @hide
+     */
+    public String getCurrentEngine() {
+        return mCurrentEngine;
+    }
+
+    /**
      * Sets the text-to-speech language.
      * The TTS engine will try to use the closest match to the specified
      * language as represented by the Locale, but there is no guarantee that the exact same Locale
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index d594567..519b980 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -119,13 +119,37 @@
      * being applied.
      * @hide
      */
-    public int unscaledWidthPixels;
+    public int noncompatWidthPixels;
     /**
      * The reported display height prior to any compatibility mode scaling
      * being applied.
      * @hide
      */
-    public int unscaledHeightPixels;
+    public int noncompatHeightPixels;
+    /**
+     * The reported display density prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public float noncompatDensity;
+    /**
+     * The reported scaled density prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public float noncompatScaledDensity;
+    /**
+     * The reported display xdpi prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public float noncompatXdpi;
+    /**
+     * The reported display ydpi prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public float noncompatYdpi;
 
     public DisplayMetrics() {
     }
@@ -138,8 +162,12 @@
         scaledDensity = o.scaledDensity;
         xdpi = o.xdpi;
         ydpi = o.ydpi;
-        unscaledWidthPixels = o.unscaledWidthPixels;
-        unscaledHeightPixels = o.unscaledHeightPixels;
+        noncompatWidthPixels = o.noncompatWidthPixels;
+        noncompatHeightPixels = o.noncompatHeightPixels;
+        noncompatDensity = o.noncompatDensity;
+        noncompatScaledDensity = o.noncompatScaledDensity;
+        noncompatXdpi = o.noncompatXdpi;
+        noncompatYdpi = o.noncompatYdpi;
     }
     
     public void setToDefaults() {
@@ -150,8 +178,8 @@
         scaledDensity = density;
         xdpi = DENSITY_DEVICE;
         ydpi = DENSITY_DEVICE;
-        unscaledWidthPixels = 0;
-        unscaledHeightPixels = 0;
+        noncompatWidthPixels = 0;
+        noncompatHeightPixels = 0;
     }
 
     @Override
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 3fa8dfd..2be5a49 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -107,8 +107,8 @@
                 CompatibilityInfo ci;
                 if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) {
                     synchronized (mTmpMetrics) {
-                        mTmpMetrics.unscaledWidthPixels = outSize.x;
-                        mTmpMetrics.unscaledHeightPixels = outSize.y;
+                        mTmpMetrics.noncompatWidthPixels = outSize.x;
+                        mTmpMetrics.noncompatHeightPixels = outSize.y;
                         mTmpMetrics.density = mDensity;
                         ci.applyToDisplayMetrics(mTmpMetrics);
                         outSize.x = mTmpMetrics.widthPixels;
@@ -268,14 +268,15 @@
     }
 
     private void getNonSizeMetrics(DisplayMetrics outMetrics) {
-        outMetrics.density      = mDensity;
         outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
-        outMetrics.scaledDensity= outMetrics.density;
-        outMetrics.xdpi         = mDpiX;
-        outMetrics.ydpi         = mDpiY;
 
-        outMetrics.unscaledWidthPixels  = outMetrics.widthPixels;
-        outMetrics.unscaledHeightPixels = outMetrics.heightPixels;
+        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels;
+        outMetrics.noncompatHeightPixels = outMetrics.heightPixels;
+
+        outMetrics.density = outMetrics.noncompatDensity = mDensity;
+        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
+        outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX;
+        outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY;
     }
 
     static IWindowManager getWindowManager() {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 5216c49..04f35dc 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -161,10 +161,11 @@
     // Hardware layers
     ///////////////////////////////////////////////////////////////////////////
     
-    static native int nCreateTextureLayer(int[] layerInfo);
+    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 nUpdateTextureLayer(int layerId, int width, int height, SurfaceTexture surface);
+    static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
+            SurfaceTexture surface);
     static native void nDestroyLayer(int layerId);
     static native void nDestroyLayerDeferred(int layerId);
     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 69dfc2b..a491a0b 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -42,9 +42,15 @@
         return mLayer;
     }
 
+    @Override
     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() {
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 063eee7..391d9f4 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -28,9 +28,9 @@
     private int mTexture;
     private SurfaceTexture mSurface;
 
-    GLES20TextureLayer() {
+    GLES20TextureLayer(boolean isOpaque) {
         int[] layerInfo = new int[2];
-        mLayer = GLES20Canvas.nCreateTextureLayer(layerInfo);
+        mLayer = GLES20Canvas.nCreateTextureLayer(isOpaque, layerInfo);
 
         if (mLayer != 0) {
             mTexture = layerInfo[0];
@@ -65,12 +65,14 @@
 
     SurfaceTexture getSurfaceTexture() {
         if (mSurface == null) {
-            mSurface = new SurfaceTexture(mTexture);
+            mSurface = new SurfaceTexture(mTexture, false);
         }
         return mSurface;
     }
 
-    void update(int width, int height) {
-        GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, mSurface);
+    @Override
+    void update(int width, int height, boolean isOpaque) {
+        super.update(width, height, isOpaque);
+        GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface);
     }
 }
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 86dec3f..dfb39ae 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 
 /**
@@ -34,7 +35,7 @@
     int mWidth;
     int mHeight;
 
-    final boolean mOpaque;
+    boolean mOpaque;
 
     /**
      * Creates a new hardware layer with undefined dimensions.
@@ -92,7 +93,7 @@
     abstract boolean isValid();
 
     /**
-     * Resizes the layer, if necessary, to be at least as large
+     * Resize the layer, if necessary, to be at least as large
      * as the supplied dimensions.
      * 
      * @param width The new desired minimum width for this layer
@@ -124,4 +125,29 @@
      * @param currentCanvas
      */
     abstract void end(Canvas currentCanvas);
+
+    /**
+     * Copies this layer into the specified bitmap.
+     * 
+     * @param bitmap The bitmap to copy they layer into
+     * 
+     * @return True if the copy was successful, false otherwise
+     */
+    abstract boolean copyInto(Bitmap bitmap);
+
+    /**
+     * Update the layer's properties. This method should be used
+     * when the underlying storage is modified by an external entity.
+     * To change the underlying storage, use the {@link #resize(int, int)}
+     * method instead.
+     * 
+     * @param width The new width of this layer
+     * @param height The new height of this layer
+     * @param isOpaque Whether this layer is opaque
+     */
+    void update(int width, int height, boolean isOpaque) {
+        mWidth = width;
+        mHeight = height;
+        mOpaque = isOpaque;
+    }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 5ceb12a..bbfb4c1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -17,12 +17,11 @@
 
 package android.view;
 
-import android.graphics.Bitmap;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
-import android.os.*;
-import android.util.EventLog;
+import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import javax.microedition.khronos.egl.EGL10;
@@ -170,9 +169,11 @@
      * Creates a new hardware layer. A hardware layer built by calling this
      * method will be treated as a texture layer, instead of as a render target.
      * 
+     * @param isOpaque Whether the layer should be opaque or not
+     * 
      * @return A hardware layer
      */    
-    abstract HardwareLayer createHardwareLayer();
+    abstract HardwareLayer createHardwareLayer(boolean isOpaque);
     
     /**
      * Creates a new hardware layer.
@@ -197,25 +198,6 @@
     abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
 
     /**
-     * Updates the specified layer.
-     * 
-     * @param layer The hardware layer to update
-     * @param width The layer's width
-     * @param height The layer's height
-     */
-    abstract void updateTextureLayer(HardwareLayer layer, int width, int height);
-
-    /**
-     * Copies the content of the specified layer into the specified bitmap.
-     * 
-     * @param layer The hardware layer to copy
-     * @param bitmap The bitmap to copy the layer into
-     * 
-     * @return True if the copy was successful, false otherwise
-     */
-    abstract boolean copyLayer(HardwareLayer layer, Bitmap bitmap);    
-
-    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewAncestor has
      * potentially lost the hardware renderer. The hardware renderer should be
@@ -339,6 +321,13 @@
         }
 
         /**
+         * Indicates whether this renderer instance can track and update dirty regions.
+         */
+        boolean hasDirtyRegions() {
+            return mDirtyRegions;
+        }
+
+        /**
          * Return a string for the EGL error code, or the hex representation
          * if the error is unknown.
          * 
@@ -631,19 +620,14 @@
         void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
                 Rect dirty) {
             if (canDraw()) {
-                if (!mDirtyRegions) {
+                if (!hasDirtyRegions()) {
                     dirty = null;
                 }
-
-                attachInfo.mDrawingTime = SystemClock.uptimeMillis();
                 attachInfo.mIgnoreDirtyState = true;
+                attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+
                 view.mPrivateFlags |= View.DRAWN;
                 
-                long startTime;
-                if (ViewDebug.DEBUG_PROFILE_DRAWING) {
-                    startTime = SystemClock.elapsedRealtime();
-                }
-
                 final int surfaceState = checkCurrent();
                 if (surfaceState != SURFACE_STATE_ERROR) {
                     // We had to change the current surface and/or context, redraw everything
@@ -697,26 +681,9 @@
 
                     onPostDraw();
 
-                    if (ViewDebug.DEBUG_PROFILE_DRAWING) {
-                        EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
-                    }
-    
                     attachInfo.mIgnoreDirtyState = false;
 
-                    final long swapBuffersStartTime;
-                    if (ViewDebug.DEBUG_LATENCY) {
-                        swapBuffersStartTime = System.nanoTime();
-                    }
-
                     sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
-
-                    if (ViewDebug.DEBUG_LATENCY) {
-                        long now = System.nanoTime();
-                        Log.d(LOG_TAG, "Latency: Spent "
-                                + ((now - swapBuffersStartTime) * 0.000001f)
-                                + "ms waiting for eglSwapBuffers()");
-                    }
-
                     checkEglErrors();
                 }
             }
@@ -803,8 +770,8 @@
         }
 
         @Override
-        HardwareLayer createHardwareLayer() {
-            return new GLES20TextureLayer();
+        HardwareLayer createHardwareLayer(boolean isOpaque) {
+            return new GLES20TextureLayer(isOpaque);
         }
 
         @Override
@@ -817,16 +784,6 @@
             return ((GLES20TextureLayer) layer).getSurfaceTexture();
         }
 
-        @Override
-        void updateTextureLayer(HardwareLayer layer, int width, int height) {
-            ((GLES20TextureLayer) layer).update(width, height);
-        }
-
-        @Override
-        boolean copyLayer(HardwareLayer layer, Bitmap bitmap) {
-            return ((GLES20Layer) layer).copyInto(bitmap);
-        }
-
         static HardwareRenderer create(boolean translucent) {
             if (GLES20Canvas.isAvailable()) {
                 return new Gl20Renderer(translucent);
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index 49f3bbe..9b081b2 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -239,7 +239,7 @@
                     break;
             }
         } finally {
-            finishEvent(false);
+            finishEvent();
         }
     }
 
@@ -302,7 +302,7 @@
                 problem("Source was not SOURCE_CLASS_TRACKBALL.");
             }
         } finally {
-            finishEvent(false);
+            finishEvent();
         }
     }
 
@@ -328,7 +328,9 @@
             mTouchEventStreamUnhandled = false;
             mTouchEventStreamPointers = 0;
         }
-        final boolean wasTainted = mTouchEventStreamIsTainted;
+        if (mTouchEventStreamIsTainted) {
+            event.setTainted(true);
+        }
 
         try {
             ensureMetaStateIsNormalized(event.getMetaState());
@@ -441,7 +443,7 @@
                 problem("Source was not SOURCE_CLASS_POINTER.");
             }
         } finally {
-            finishEvent(wasTainted);
+            finishEvent();
         }
     }
 
@@ -499,7 +501,7 @@
                 }
             }
         } finally {
-            finishEvent(false);
+            finishEvent();
         }
     }
 
@@ -591,9 +593,9 @@
         return true;
     }
 
-    private void finishEvent(boolean tainted) {
+    private void finishEvent() {
         if (mViolationMessage != null && mViolationMessage.length() != 0) {
-            if (!tainted) {
+            if (!mCurrentEvent.isTainted()) {
                 // Write a log message only if the event was not already tainted.
                 mViolationMessage.append("\n  in ").append(mCaller);
                 mViolationMessage.append("\n  ");
@@ -614,17 +616,14 @@
                 }
 
                 Log.d(mLogTag, mViolationMessage.toString());
-                tainted = true;
+
+                // Taint the event so that we do not generate additional violations from it
+                // further downstream.
+                mCurrentEvent.setTainted(true);
             }
             mViolationMessage.setLength(0);
         }
 
-        if (tainted) {
-            // Taint the event so that we do not generate additional violations from it
-            // further downstream.
-            mCurrentEvent.setTainted(true);
-        }
-
         if (RECENT_EVENTS_TO_LOG != 0) {
             if (mRecentEvents == null) {
                 mRecentEvents = new InputEvent[RECENT_EVENTS_TO_LOG];
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 5dbda90..6c3d387 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2361,11 +2361,11 @@
      * Gets the {@link KeyCharacterMap} associated with the keyboard device.
      *
      * @return The associated key character map.
-     * @throws {@link UnavailableException} if the key character map
+     * @throws {@link KeyCharacterMap.UnavailableException} if the key character map
      * could not be loaded because it was malformed or the default key character map
      * is missing from the system.
      *
-     * @see {@link KeyCharacterMap#load}
+     * @see KeyCharacterMap#load
      */
     public final KeyCharacterMap getKeyCharacterMap() {
         return KeyCharacterMap.load(mDeviceId);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 3436cd1..88f59d4 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1130,14 +1130,14 @@
     public static final int BUTTON_PRIMARY = 1 << 0;
 
     /**
-     * Button constant: Secondary button (right mouse button, stylus barrel).
+     * Button constant: Secondary button (right mouse button, stylus first button).
      *
      * @see #getButtonState
      */
     public static final int BUTTON_SECONDARY = 1 << 1;
 
     /**
-     * Button constant: Tertiary button (middle mouse button).
+     * Button constant: Tertiary button (middle mouse button, stylus second button).
      *
      * @see #getButtonState
      */
@@ -1165,13 +1165,6 @@
      */
     public static final int BUTTON_FORWARD = 1 << 4;
 
-    /**
-     * Button constant: Eraser button pressed (stylus end).
-     *
-     * @see #getButtonState
-     */
-    public static final int BUTTON_ERASER = 1 << 5;
-
     // NOTE: If you add a new axis here you must also add it to:
     //  native/include/android/input.h
 
@@ -1183,7 +1176,7 @@
         "BUTTON_TERTIARY",
         "BUTTON_BACK",
         "BUTTON_FORWARD",
-        "BUTTON_ERASER",
+        "0x00000020",
         "0x00000040",
         "0x00000080",
         "0x00000100",
@@ -2176,7 +2169,6 @@
      * @see #BUTTON_TERTIARY
      * @see #BUTTON_FORWARD
      * @see #BUTTON_BACK
-     * @see #BUTTON_ERASER
      */
     public final int getButtonState() {
         return nativeGetButtonState(mNativePtr);
@@ -2893,7 +2885,7 @@
                     toolTypeToString(getToolType(i)));
         }
 
-        msg.append(", buttonState=").append(KeyEvent.metaStateToString(getButtonState()));
+        msg.append(", buttonState=").append(MotionEvent.buttonStateToString(getButtonState()));
         msg.append(", metaState=").append(KeyEvent.metaStateToString(getMetaState()));
         msg.append(", flags=0x").append(Integer.toHexString(getFlags()));
         msg.append(", edgeFlags=0x").append(Integer.toHexString(getEdgeFlags()));
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 0421205..d656f31 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -67,15 +67,19 @@
  *              // Something bad happened
  *          }
  *      }
- *      
+ *
  *      public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  *          // Ignored, Camera does all the work for us
  *      }
- *      
+ *
  *      public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
  *          mCamera.stopPreview();
  *          mCamera.release();
  *      }
+ *
+ *      public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ *          // Invoked every time there's a new Camera preview frame
+ *      }
  *  }
  * </pre>
  * 
@@ -96,12 +100,11 @@
     private SurfaceTexture mSurface;
     private SurfaceTextureListener mListener;
 
-    private final Runnable mUpdateLayerAction = new Runnable() {
-        @Override
-        public void run() {
-            updateLayer();
-        }
-    };
+    private boolean mOpaque = true;
+
+    private final Object[] mLock = new Object[0];
+    private boolean mUpdateLayer;
+
     private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
 
     /**
@@ -146,6 +149,28 @@
         mLayerPaint = new Paint();
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    /**
+     * Indicates whether the content of this TextureView is opaque. The
+     * content is assumed to be opaque by default.
+     * 
+     * @param opaque True if the content of this TextureView is opaque,
+     *               false otherwise
+     */
+    public void setOpaque(boolean opaque) {
+        if (opaque != mOpaque) {
+            mOpaque = opaque;
+            updateLayer();
+        }
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -160,7 +185,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
-        if (isHardwareAccelerated() && mLayer != null) {
+        if (mLayer != null) {
             if (mListener != null) {
                 mListener.onSurfaceTextureDestroyed(mSurface);
             }
@@ -215,7 +240,7 @@
      */
     @Override
     public final void draw(Canvas canvas) {
-        super.draw(canvas);
+        applyUpdate();
     }
 
     /**
@@ -241,12 +266,12 @@
 
     @Override
     HardwareLayer getHardwareLayer() {
-        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
-            return null;
-        }
-
         if (mLayer == null) {
-            mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer();
+            if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+                return null;
+            }
+
+            mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
             mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
 
@@ -255,7 +280,10 @@
                 public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                     // Per SurfaceTexture's documentation, the callback may be invoked
                     // from an arbitrary thread
-                    post(mUpdateLayerAction);
+                    synchronized (mLock) {
+                        mUpdateLayer = true;
+                    }
+                    postInvalidateDelayed(0);
                 }
             };
             mSurface.setOnFrameAvailableListener(mUpdateListener);
@@ -265,6 +293,8 @@
             }
         }
 
+        applyUpdate();
+
         return mLayer;
     }
 
@@ -286,13 +316,28 @@
     }
 
     private void updateLayer() {
-        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+        mUpdateLayer = true;
+        invalidate();
+    }
+    
+    private void applyUpdate() {
+        if (mLayer == null) {
             return;
         }
 
-        mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight());
+        synchronized (mLock) {
+            if (mUpdateLayer) {
+                mUpdateLayer = false;
+            } else {
+                return;
+            }
+        }
+        
+        mLayer.update(getWidth(), getHeight(), mOpaque);
 
-        invalidate();
+        if (mListener != null) {
+            mListener.onSurfaceTextureUpdated(mSurface);
+        }
     }
 
     /**
@@ -371,7 +416,7 @@
      */
     public Bitmap getBitmap(Bitmap bitmap) {
         if (bitmap != null && isAvailable()) {
-            mAttachInfo.mHardwareRenderer.copyLayer(mLayer, bitmap);
+            mLayer.copyInto(bitmap);
         }
         return bitmap;
     }
@@ -451,6 +496,14 @@
          * @param surface The surface about to be destroyed
          */
         public void onSurfaceTextureDestroyed(SurfaceTexture surface);
+
+        /**
+         * Invoked when the specified {@link SurfaceTexture} is updated through
+         * {@link SurfaceTexture#updateTexImage()}.
+         * 
+         * @param surface The surface just updated
+         */
+        public void onSurfaceTextureUpdated(SurfaceTexture surface);
     }
 
     private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f70ca90..bf7f359 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2326,6 +2326,7 @@
     private CheckForLongPress mPendingCheckForLongPress;
     private CheckForTap mPendingCheckForTap = null;
     private PerformClick mPerformClick;
+    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
 
     private UnsetPressedState mUnsetPressedState;
 
@@ -2492,6 +2493,84 @@
     private boolean mSendingHoverAccessibilityEvents;
 
     /**
+     * Undefined text direction (used by resolution algorithm).
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_UNDEFINED = -1;
+
+    /**
+     * Text direction is inherited thru {@link ViewGroup}
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_INHERIT = 0;
+
+    /**
+     * Text direction is using "first strong algorithm". The first strong directional character
+     * determines the paragraph direction. If there is no strong directional character, the
+     * paragraph direction is the view’s resolved ayout direction.
+     *
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
+
+    /**
+     * 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;
+
+    /**
+     * Default text direction is inherited
+     */
+    protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
+
+    /**
+     * The text direction that has been defined by {@link #setTextDirection(int)}.
+     *
+     * {@hide}
+     */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_UNDEFINED, to = "UNDEFINED"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
+    })
+    protected int mTextDirection = DEFAULT_TEXT_DIRECTION;
+
+    /**
+     * The resolved text direction. If resolution has not yet been done or has been reset, it will
+     * be equal to {@link #TEXT_DIRECTION_UNDEFINED}. Otherwise it will be either {@link #TEXT_DIRECTION_LTR}
+     * or {@link #TEXT_DIRECTION_RTL}.
+     *
+     * {@hide}
+     */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_UNDEFINED, to = "UNDEFINED"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
+    })
+    protected int mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+
+    /**
      * Consistency verifier for debugging purposes.
      * @hide
      */
@@ -2864,6 +2943,9 @@
                 case R.styleable.View_layerType:
                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                     break;
+                case R.styleable.View_textDirection:
+                    mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
+                    break;
             }
         }
 
@@ -3389,6 +3471,14 @@
     }
 
     /**
+     * Register a callback to be invoked when a hover event is sent to this view.
+     * @param l the hover listener to attach to this view
+     */
+    public void setOnHoverListener(OnHoverListener l) {
+        mOnHoverListener = l;
+    }
+
+    /**
      * Register a drag event listener callback object for this View. The parameter is
      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
      * View, the system calls the
@@ -3699,7 +3789,6 @@
      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
      */
     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
-
     }
 
     /**
@@ -3728,12 +3817,23 @@
         event.setEnabled(isEnabled());
         event.setContentDescription(mContentDescription);
 
-        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
-            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
-            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
-            event.setItemCount(focusablesTempList.size());
-            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
-            focusablesTempList.clear();
+        final int eventType = event.getEventType();
+        switch (eventType) {
+            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
+                if (mAttachInfo != null) {
+                    ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
+                    getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
+                            FOCUSABLES_ALL);
+                    event.setItemCount(focusablesTempList.size());
+                    event.setCurrentItemIndex(focusablesTempList.indexOf(this));
+                    focusablesTempList.clear();
+                }
+            } break;
+            case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
+                event.setScrollX(mScrollX);
+                event.setScrollY(mScrollY);
+                event.setItemCount(getHeight());
+            } break;
         }
     }
 
@@ -4345,19 +4445,25 @@
     }
 
     /**
-     * Set the layout direction for this view.
+     * Set the layout direction for this view. This will propagate a reset of layout direction
+     * resolution to the view's children and resolve layout direction for this view.
      *
      * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
      *   {@link #LAYOUT_DIRECTION_RTL},
      *   {@link #LAYOUT_DIRECTION_INHERIT} or
      *   {@link #LAYOUT_DIRECTION_LOCALE}.
+     *
      * @attr ref android.R.styleable#View_layoutDirection
      *
      * @hide
      */
     @RemotableViewMethod
     public void setLayoutDirection(int layoutDirection) {
-        setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
+        if (getLayoutDirection() != layoutDirection) {
+            resetLayoutDirectionResolution();
+            // Setting the flag will also request a layout.
+            setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
+        }
     }
 
     /**
@@ -5121,12 +5227,7 @@
             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
         }
 
-        //Log.i("view", "view=" + this + ", " + event.toString());
-        if (onTrackballEvent(event)) {
-            return true;
-        }
-
-        return false;
+        return onTrackballEvent(event);
     }
 
     /**
@@ -5221,6 +5322,7 @@
                 break;
         }
 
+        //noinspection SimplifiableIfStatement
         if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
                 && mOnHoverListener.onHover(this, event)) {
             return true;
@@ -5893,6 +5995,7 @@
      */
     private boolean isHoverable() {
         final int viewFlags = mViewFlags;
+        //noinspection SimplifiableIfStatement
         if ((viewFlags & ENABLED_MASK) == DISABLED) {
             return false;
         }
@@ -6162,6 +6265,16 @@
     }
 
     /**
+     * Remove the pending callback for sending a
+     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+     */
+    private void removeSendViewScrolledAccessibilityEventCallback() {
+        if (mSendViewScrolledAccessibilityEvent != null) {
+            removeCallbacks(mSendViewScrolledAccessibilityEvent);
+        }
+    }
+
+    /**
      * Sets the TouchDelegate for this View.
      */
     public void setTouchDelegate(TouchDelegate delegate) {
@@ -6334,6 +6447,10 @@
      * @param oldt Previous vertical scroll origin.
      */
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            postSendViewScrolledAccessibilityEventCallback();
+        }
+
         mBackgroundSizeChanged = true;
 
         final AttachInfo ai = mAttachInfo;
@@ -8260,6 +8377,22 @@
     }
 
     /**
+     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
+     * This event is sent at most once every
+     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
+     */
+    private void postSendViewScrolledAccessibilityEventCallback() {
+        if (mSendViewScrolledAccessibilityEvent == null) {
+            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
+        }
+        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
+            mSendViewScrolledAccessibilityEvent.mIsPending = true;
+            postDelayed(mSendViewScrolledAccessibilityEvent,
+                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+        }
+    }
+
+    /**
      * Called by a parent to request that a child update its values for mScrollX
      * and mScrollY if necessary. This will typically be done if the child is
      * animating a scroll using a {@link android.widget.Scroller Scroller}
@@ -8899,6 +9032,8 @@
         resetLayoutDirectionResolution();
         resolveLayoutDirectionIfNeeded();
         resolvePadding();
+        resetResolvedTextDirection();
+        resolveTextDirection();
         if (isFocused()) {
             InputMethodManager imm = InputMethodManager.peekInstance();
             imm.focusIn(this);
@@ -8988,7 +9123,8 @@
     /**
      * Reset the resolved layout direction by clearing the corresponding flag
      */
-    private void resetLayoutDirectionResolution() {
+    void resetLayoutDirectionResolution() {
+        // Reset the current View resolution
         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
     }
 
@@ -8998,7 +9134,7 @@
      * @param locale Locale to check
      * @return true if a Locale is corresponding to a RTL script.
      */
-    private static boolean isLayoutDirectionRtl(Locale locale) {
+    protected static boolean isLayoutDirectionRtl(Locale locale) {
         return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
                 LocaleUtil.getLayoutDirectionFromLocale(locale));
     }
@@ -9015,6 +9151,7 @@
         removeUnsetPressCallback();
         removeLongPressCallback();
         removePerformClickCallback();
+        removeSendViewScrolledAccessibilityEventCallback();
 
         destroyDrawingCache();
 
@@ -9674,10 +9811,10 @@
                 computeScroll();
                 canvas.translate(-mScrollX, -mScrollY);
                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~DIRTY_MASK;
 
                 // Fast path for layouts with no backgrounds
                 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                    mPrivateFlags &= ~DIRTY_MASK;
                     dispatchDraw(canvas);
                 } else {
                     draw(canvas);
@@ -11826,6 +11963,10 @@
         mPrivateFlags |= FORCE_LAYOUT;
         mPrivateFlags |= INVALIDATED;
 
+        if (mLayoutParams != null) {
+            mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
+        }
+
         if (mParent != null && !mParent.isLayoutRequested()) {
             mParent.requestLayout();
         }
@@ -12840,6 +12981,89 @@
         return getVerticalScrollFactor();
     }
 
+    /**
+     * Return the value specifying the text direction or policy that was set with
+     * {@link #setTextDirection(int)}.
+     *
+     * @return the defined text direction. It can be one of:
+     *
+     * {@link #TEXT_DIRECTION_INHERIT},
+     * {@link #TEXT_DIRECTION_FIRST_STRONG}
+     * {@link #TEXT_DIRECTION_ANY_RTL},
+     * {@link #TEXT_DIRECTION_LTR},
+     * {@link #TEXT_DIRECTION_RTL},
+     *
+     * @hide
+     */
+    public int getTextDirection() {
+        return mTextDirection;
+    }
+
+    /**
+     * Set the text direction.
+     *
+     * @param textDirection the direction to set. Should be one of:
+     *
+     * {@link #TEXT_DIRECTION_INHERIT},
+     * {@link #TEXT_DIRECTION_FIRST_STRONG}
+     * {@link #TEXT_DIRECTION_ANY_RTL},
+     * {@link #TEXT_DIRECTION_LTR},
+     * {@link #TEXT_DIRECTION_RTL},
+     *
+     * @hide
+     */
+    public void setTextDirection(int textDirection) {
+        if (textDirection != mTextDirection) {
+            mTextDirection = textDirection;
+            resetResolvedTextDirection();
+            requestLayout();
+        }
+    }
+
+    /**
+     * Return the resolved text direction.
+     *
+     * @return the resolved text direction. Return one of:
+     *
+     * {@link #TEXT_DIRECTION_LTR},
+     * {@link #TEXT_DIRECTION_RTL},
+     *
+     * @hide
+     */
+    public int getResolvedTextDirection() {
+        if (!isResolvedTextDirection()) {
+            resolveTextDirection();
+        }
+        return mResolvedTextDirection;
+    }
+
+    /**
+     * Resolve the text direction. Classes that extend View and want to do a specific text direction
+     * resolution will need to implement this method and set the mResolvedTextDirection to
+     * either TEXT_DIRECTION_LTR if direction is LTR or TEXT_DIRECTION_RTL if
+     * direction is RTL.
+     */
+    protected void resolveTextDirection() {
+    }
+
+    /**
+     * Return if the text direction has been resolved or not.
+     *
+     * @return true, if resolved and false if not resolved
+     *
+     * @hide
+     */
+    public boolean isResolvedTextDirection() {
+        return (mResolvedTextDirection != TEXT_DIRECTION_UNDEFINED);
+    }
+
+    /**
+     * Reset resolved text direction. Will be resolved during a call to getResolvedLayoutDirection().
+     */
+    protected void resetResolvedTextDirection() {
+        mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+    }
+
     //
     // Properties
     //
@@ -12847,7 +13071,7 @@
      * A Property wrapper around the <code>alpha</code> functionality handled by the
      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
      */
-    static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
+    public static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
         @Override
         public void setValue(View object, float value) {
             object.setAlpha(value);
@@ -13573,6 +13797,12 @@
         boolean mIgnoreDirtyState;
 
         /**
+         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
+         * to avoid clearing that flag prematurely.
+         */
+        boolean mSetIgnoreDirtyState = false;
+
+        /**
          * Indicates whether the view's window is currently in touch mode.
          */
         boolean mInTouchMode;
@@ -13806,6 +14036,18 @@
                 host.invalidate(true);
             }
         }
+    }
 
+    /**
+     * Resuable callback for sending
+     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+     */
+    private class SendViewScrolledAccessibilityEvent implements Runnable {
+        public volatile boolean mIsPending;
+
+        public void run() {
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+            mIsPending = false;
+        }
     }
 }
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index afbedaf..2b692f3 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -136,13 +136,6 @@
     static final ArrayList<ComponentCallbacks> sConfigCallbacks
             = new ArrayList<ComponentCallbacks>();
 
-    /**
-     * Delay before dispatching an accessibility event that the window
-     * content has changed. The window content is considered changed
-     * after a layout pass.
-     */
-    private static final long SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS = 500;
-
     long mLastTrackballTime = 0;
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -284,7 +277,7 @@
 
     AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
 
-    SendWindowContentChanged mSendWindowContentChanged;
+    SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
 
     private final int mDensity;
 
@@ -672,6 +665,7 @@
             }
         }
         if (!mDirty.isEmpty() && !mDirty.contains(dirty)) {
+            mAttachInfo.mSetIgnoreDirtyState = true;
             mAttachInfo.mIgnoreDirtyState = true;
         }
         mDirty.union(dirty);
@@ -1000,8 +994,7 @@
                     + "x" + desiredWindowHeight + "...");
 
             boolean goodMeasure = false;
-            if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
-                    || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
+            if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
                 // On large screens, we don't want to allow dialogs to just
                 // stretch to fill the entire width of the screen to display
                 // one line of text.  First try doing the layout at a smaller
@@ -1748,7 +1741,7 @@
             mAttachInfo.mIgnoreDirtyState = true;
             dirty.union(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
         }
-        
+
         if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
             if (!dirty.isEmpty() || mIsAnimating) {
                 mIsAnimating = false;
@@ -1878,9 +1871,13 @@
                         }
                         canvas.setScreenDensity(scalingRequired
                                 ? DisplayMetrics.DENSITY_DEVICE : 0);
+                        mAttachInfo.mSetIgnoreDirtyState = false;
                         mView.draw(canvas);
                     } finally {
-                        mAttachInfo.mIgnoreDirtyState = false;
+                        if (!mAttachInfo.mSetIgnoreDirtyState) {
+                            // Only clear the flag if it was not set during the mView.draw() call
+                            mAttachInfo.mIgnoreDirtyState = false;
+                        }
                     }
 
                     if (false && ViewDebug.consistencyCheckEnabled) {
@@ -3688,14 +3685,19 @@
     /**
      * Post a callback to send a
      * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
+     * This event is send at most once every
+     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
      */
     private void postSendWindowContentChangedCallback() {
-        if (mSendWindowContentChanged == null) {
-            mSendWindowContentChanged = new SendWindowContentChanged();
-        } else {
-            removeCallbacks(mSendWindowContentChanged);
+        if (mSendWindowContentChangedAccessibilityEvent == null) {
+            mSendWindowContentChangedAccessibilityEvent =
+                new SendWindowContentChangedAccessibilityEvent();
         }
-        postDelayed(mSendWindowContentChanged, SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS);
+        if (!mSendWindowContentChangedAccessibilityEvent.mIsPending) {
+            mSendWindowContentChangedAccessibilityEvent.mIsPending = true;
+            postDelayed(mSendWindowContentChangedAccessibilityEvent,
+                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+        }
     }
 
     /**
@@ -3703,8 +3705,8 @@
      * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
      */
     private void removeSendWindowContentChangedCallback() {
-        if (mSendWindowContentChanged != null) {
-            removeCallbacks(mSendWindowContentChanged);
+        if (mSendWindowContentChangedAccessibilityEvent != null) {
+            removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
         }
     }
 
@@ -4630,10 +4632,19 @@
         }
     }
 
-    private class SendWindowContentChanged implements Runnable {
+    private class SendWindowContentChangedAccessibilityEvent implements Runnable {
+        public volatile boolean mIsPending;
+
         public void run() {
             if (mView != null) {
-                mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+                // Send the event directly since we do not want to append the
+                // source text because this is the text for the entire window
+                // and we just want to notify that the content has changed.
+                AccessibilityEvent event = AccessibilityEvent.obtain(
+                        AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+                mView.onInitializeAccessibilityEvent(event);
+                AccessibilityManager.getInstance(mView.mContext).sendAccessibilityEvent(event);
+                mIsPending = false;
             }
         }
     }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5919150..f3a5050 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -176,6 +176,14 @@
     private static final int TOUCH_EXPLORATION_TAP_SLOP = 80;
 
     /**
+     * Delay before dispatching a recurring accessibility event in milliseconds.
+     * This delay guarantees that a recurring event will be send at most once
+     * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time
+     * frame.
+     */
+    private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 400;
+
+    /**
      * The maximum size of View's drawing cache, expressed in bytes. This size
      * should be at least equal to the size of the screen in ARGB888 format.
      */
@@ -498,6 +506,19 @@
     }
 
     /**
+     * Interval for dispatching a recurring accessibility event in milliseconds.
+     * This interval guarantees that a recurring event will be send at most once
+     * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame.
+     *
+     * @return The delay in milliseconds.
+     *
+     * @hide
+     */
+    public static long getSendRecurringAccessibilityEventsInterval() {
+        return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
+    }
+
+    /**
      * @return Distance a touch must be outside the bounds of a window for it
      * to be counted as outside the window for purposes of dismissing that
      * window.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e928f80..2a90dde 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -46,6 +46,7 @@
 
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Locale;
 
 /**
  * <p>
@@ -1233,6 +1234,7 @@
     /**
      * {@inheritDoc}
      */
+    @SuppressWarnings({"ConstantConditions"})
     @Override
     protected boolean dispatchHoverEvent(MotionEvent event) {
         final int action = event.getAction();
@@ -3876,8 +3878,10 @@
                 if (!childMatrix.isIdentity()) {
                     RectF boundingRect = attachInfo.mTmpTransformRect;
                     boundingRect.set(dirty);
+                    //boundingRect.inset(-0.5f, -0.5f);
                     childMatrix.mapRect(boundingRect);
-                    dirty.set((int) boundingRect.left, (int) boundingRect.top,
+                    dirty.set((int) (boundingRect.left - 0.5f),
+                            (int) (boundingRect.top - 0.5f),
                             (int) (boundingRect.right + 0.5f),
                             (int) (boundingRect.bottom + 0.5f));
                 }
@@ -4995,6 +4999,69 @@
     }
 
     /**
+     * This method will be called when we need to reset the layout direction resolution flag
+     *
+     */
+    @Override
+    void resetLayoutDirectionResolution() {
+        super.resetLayoutDirectionResolution();
+
+        // Take care of resetting the children resolution too
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getLayoutDirection() == LAYOUT_DIRECTION_INHERIT) {
+                child.resetLayoutDirectionResolution();
+            }
+        }
+    }
+
+    /**
+     * This method will be called during text direction resolution (text direction resolution
+     * inheritance)
+     */
+    @Override
+    protected void resolveTextDirection() {
+        int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+        switch(mTextDirection) {
+            default:
+            case TEXT_DIRECTION_INHERIT:
+                // Try to the text direction from the parent layout
+                if (mParent != null && mParent instanceof ViewGroup) {
+                    resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+                } else {
+                    // We reached the top of the View hierarchy, so get the direction from
+                    // the Locale
+                    resolvedTextDirection = isLayoutDirectionRtl(Locale.getDefault()) ?
+                            TEXT_DIRECTION_RTL : TEXT_DIRECTION_LTR;
+                }
+                break;
+            // Pass down the hierarchy the following text direction values
+            case TEXT_DIRECTION_FIRST_STRONG:
+            case TEXT_DIRECTION_ANY_RTL:
+            case TEXT_DIRECTION_LTR:
+            case TEXT_DIRECTION_RTL:
+                resolvedTextDirection = mTextDirection;
+                break;
+        }
+        mResolvedTextDirection = resolvedTextDirection;
+    }
+
+    @Override
+    protected void resetResolvedTextDirection() {
+        super.resetResolvedTextDirection();
+
+        // Take care of resetting the children resolution too
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getTextDirection() == TEXT_DIRECTION_INHERIT) {
+                child.resetResolvedTextDirection();
+            }
+        }
+    }
+
+    /**
      * Return true if the pressed state should be delayed for children or descendants of this
      * ViewGroup. Generally, this should be done for containers that can scroll, such as a List.
      * This prevents the pressed state from appearing when the user is actually trying to scroll
@@ -5154,6 +5221,21 @@
         }
 
         /**
+         * Resolve layout parameters depending on the layout direction. Subclasses that care about
+         * layoutDirection changes should override this method. The default implementation does
+         * nothing.
+         *
+         * @param layoutDirection the direction of the layout
+         *
+         * {@link View#LAYOUT_DIRECTION_LTR}
+         * {@link View#LAYOUT_DIRECTION_RTL}
+         *
+         * @hide
+         */
+        protected void resolveWithDirection(int layoutDirection) {
+        }
+
+        /**
          * Returns a String representation of this set of layout parameters.
          *
          * @param output the String to prepend to the internal representation
@@ -5194,30 +5276,56 @@
      */
     public static class MarginLayoutParams extends ViewGroup.LayoutParams {
         /**
-         * The left margin in pixels of the child.
+         * The left margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int leftMargin;
 
         /**
-         * The top margin in pixels of the child.
+         * The top margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int topMargin;
 
         /**
-         * The right margin in pixels of the child.
+         * The right margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int rightMargin;
 
         /**
-         * The bottom margin in pixels of the child.
+         * The bottom margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int bottomMargin;
 
         /**
+         * The start margin in pixels of the child.
+         *
+         * @hide
+         *
+         */
+        @ViewDebug.ExportedProperty(category = "layout")
+        protected int startMargin = DEFAULT_RELATIVE;
+
+        /**
+         * The end margin in pixels of the child.
+         *
+         * @hide
+         */
+        @ViewDebug.ExportedProperty(category = "layout")
+        protected int endMargin = DEFAULT_RELATIVE;
+
+        /**
+         * The default start and end margin.
+         */
+        static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+
+        /**
          * Creates a new set of layout parameters. The values are extracted from
          * the supplied attributes set and context.
          *
@@ -5249,6 +5357,10 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
                 bottomMargin = a.getDimensionPixelSize(
                         R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
+                startMargin = a.getDimensionPixelSize(
+                        R.styleable.ViewGroup_MarginLayout_layout_marginStart, DEFAULT_RELATIVE);
+                endMargin = a.getDimensionPixelSize(
+                        R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
             a.recycle();
@@ -5274,6 +5386,8 @@
             this.topMargin = source.topMargin;
             this.rightMargin = source.rightMargin;
             this.bottomMargin = source.bottomMargin;
+            this.startMargin = source.startMargin;
+            this.endMargin = source.endMargin;
         }
 
         /**
@@ -5284,7 +5398,9 @@
         }
 
         /**
-         * Sets the margins, in pixels.
+         * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs
+         * to be done so that the new margins are taken into account. Left and right margins may be
+         * overriden by {@link android.view.View#requestLayout()} depending on layout direction.
          *
          * @param left the left margin size
          * @param top the top margin size
@@ -5302,6 +5418,92 @@
             rightMargin = right;
             bottomMargin = bottom;
         }
+
+        /**
+         * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()}
+         * needs to be done so that the new relative margins are taken into account. Left and right
+         * margins may be overriden by {@link android.view.View#requestLayout()} depending on layout
+         * direction.
+         *
+         * @param start the start margin size
+         * @param top the top margin size
+         * @param end the right margin size
+         * @param bottom the bottom margin size
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+         * @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) {
+            startMargin = start;
+            topMargin = top;
+            endMargin = end;
+            bottomMargin = bottom;
+        }
+
+        /**
+         * Returns the start margin in pixels.
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+         *
+         * @return the start margin in pixels.
+         *
+         * @hide
+         */
+        public int getMarginStart() {
+            return startMargin;
+        }
+
+        /**
+         * Returns the end margin in pixels.
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+         *
+         * @return the end margin in pixels.
+         *
+         * @hide
+         */
+        public int getMarginEnd() {
+            return endMargin;
+        }
+
+        /**
+         * Check if margins are relative.
+         *
+         * @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
+         */
+        public boolean isMarginRelative() {
+            return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
+        }
+
+        /**
+         * This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
+         * maybe overriden depending on layout direction.
+         *
+         * @hide
+         */
+        @Override
+        protected void resolveWithDirection(int layoutDirection) {
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
+                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
+                    break;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
+                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
+                    break;
+            }
+        }
     }
 
     /* Describes a touched view and the ids of the pointers that it has captured.
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 30d6489..25f01a7 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -56,76 +56,132 @@
  * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
  * Type:{@link #TYPE_VIEW_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
  * <p>
  * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
  * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
  * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
  * <p>
  * <b>View selected</b> - represents the event of selecting an item usually in
  * the context of an {@link android.widget.AdapterView}. <br>
  * Type: {@link #TYPE_VIEW_SELECTED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ *   <li>{@link #getItemCount()} -The number of selectable items of the source.</li>
+ *   <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
+ * </ul>
+ * <p>
  * <p>
  * <b>View focused</b> - represents the event of focusing a
  * {@link android.view.View}. <br>
  * Type: {@link #TYPE_VIEW_FOCUSED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ *   <li>{@link #getItemCount()} -The number of focusable items on the screen.</li>
+ *   <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
+ * </ul>
  * <p>
  * <b>View text changed</b> - represents the event of changing the text of an
  * {@link android.widget.EditText}. <br>
  * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()},
- * {@link #getFromIndex()},
- * {@link #getAddedCount()},
- * {@link #getRemovedCount()},
- * {@link #getBeforeText()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ *   <li>{@link #getFromIndex()} - The text change start index.</li>
+ *   <li>{@link #getAddedCount()} - The number of added characters.</li>
+ *   <li>{@link #getRemovedCount()} - The number of removed characters.</li>
+ *   <li>{@link #getBeforeText()} - The text of the source before the change.</li>
+ * </ul>
+ * <p>
+ * <b>View text selection changed</b> - represents the event of changing the text
+ * selection of an {@link android.widget.EditText}.<br>
+ * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} <br>
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #getFromIndex()} - The selection start index.</li>
+ *   <li>{@link #getToIndex()} - The selection end index.</li>
+ *   <li>{@link #getItemCount()} - The length of the source text.</li>
+ * <ul>
+ * <p>
+ * <b>View scrolled</b> - represents the event of scrolling a view. If
+ * the source is a descendant of {@link android.widget.AdapterView} the
+ * scroll is reported in terms of visible items - the first visible item,
+ * the last visible item, and the total items - because the the source
+ * is unaware if its pixel size since its adapter is responsible for
+ * creating views. In all other cases the scroll is reported as the current
+ * scroll on the X and Y axis respectively plus the height of the source in
+ * pixels.<br>
+ * Type: {@link #TYPE_VIEW_SCROLLED} <br>
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #getScrollX()} - The horizontal offset of the source
+ *                                (without descendants of AdapterView)).</li>
+ *   <li>{@link #getScrollY()} - The vertical offset of the source
+ *                                (without descendants of AdapterView)).</li>
+ *   <li>{@link #getFromIndex()} - The index of the first visible item of the source
+ *                                 (for descendants of AdapterView).</li>
+ *   <li>{@link #getToIndex()} - The index of the last visible item of the source
+ *                               (for descendants of AdapterView).</li>
+ *   <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView)
+ *                                 or the height of the source in pixels (all other cases).</li>
+ * <ul>
  * <p>
  * <b>TRANSITION TYPES</b> <br>
  * <p>
@@ -133,33 +189,40 @@
  * {@link android.widget.PopupWindow}, {@link android.view.Menu},
  * {@link android.app.Dialog}, etc. <br>
  * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ * </ul>
  * <p>
  * <b>Window content changed</b> - represents the event of change in the
  * content of a window. This change can be adding/removing view, changing
  * a view size, etc.<br>
  * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ * <ul>
  * <p>
  * <b>NOTIFICATION TYPES</b> <br>
  * <p>
  * <b>Notification state changed</b> - represents the event showing/hiding
  * {@link android.app.Notification}.
  * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
- * {@link #getParcelableData()}
+ * Properties:</br>
+ * <ul>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
+ * </ul>
  * <p>
  * <b>Security note</b>
  * <p>
@@ -258,6 +321,16 @@
     public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
 
     /**
+     * Represents the event of scrolling a view.
+     */
+    public static final int TYPE_VIEW_SCROLLED = 0x00001000;
+
+    /**
+     * Represents the event of changing the selection in an {@link android.widget.EditText}.
+     */
+    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
+
+    /**
      * Mask for {@link AccessibilityEvent} all types.
      *
      * @see #TYPE_VIEW_CLICKED
@@ -564,6 +637,9 @@
         record.mCurrentItemIndex = parcel.readInt();
         record.mItemCount = parcel.readInt();
         record.mFromIndex = parcel.readInt();
+        record.mToIndex = parcel.readInt();
+        record.mScrollX = parcel.readInt();
+        record.mScrollY =  parcel.readInt();
         record.mAddedCount = parcel.readInt();
         record.mRemovedCount = parcel.readInt();
         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
@@ -613,6 +689,9 @@
         parcel.writeInt(record.mCurrentItemIndex);
         parcel.writeInt(record.mItemCount);
         parcel.writeInt(record.mFromIndex);
+        parcel.writeInt(record.mToIndex);
+        parcel.writeInt(record.mScrollX);
+        parcel.writeInt(record.mScrollY);
         parcel.writeInt(record.mAddedCount);
         parcel.writeInt(record.mRemovedCount);
         TextUtils.writeToParcel(record.mClassName, parcel, flags);
@@ -657,8 +736,12 @@
                 builder.append("; IsPassword: " + record.isPassword());
                 builder.append("; IsChecked: " + record.isChecked());
                 builder.append("; IsFullScreen: " + record.isFullScreen());
+                builder.append("; Scrollable: " + record.isScrollable());
                 builder.append("; BeforeText: " + record.mBeforeText);
                 builder.append("; FromIndex: " + record.mFromIndex);
+                builder.append("; ToIndex: " + record.mToIndex);
+                builder.append("; ScrollX: " + record.mScrollX);
+                builder.append("; ScrollY: " + record.mScrollY);
                 builder.append("; AddedCount: " + record.mAddedCount);
                 builder.append("; RemovedCount: " + record.mRemovedCount);
                 builder.append("; ParcelableData: " + record.mParcelableData);
@@ -704,6 +787,10 @@
                 return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
             case TYPE_WINDOW_CONTENT_CHANGED:
                 return "TYPE_WINDOW_CONTENT_CHANGED";
+            case TYPE_VIEW_TEXT_SELECTION_CHANGED:
+                return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
+            case TYPE_VIEW_SCROLLED:
+                return "TYPE_VIEW_SCROLLED";
             default:
                 return null;
         }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 555667b..dbbe7be 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -83,6 +83,8 @@
 
     private static final int PROPERTY_PASSWORD = 0x00000100;
 
+    private static final int PROPERTY_SCROLLABLE = 0x00000200;
+
     // Readable representations - lazily initialized.
     private static SparseArray<String> sActionSymbolicNames;
 
@@ -570,6 +572,27 @@
     }
 
     /**
+     * Gets if the node is scrollable.
+     *
+     * @return True if the node is scrollable, false otherwise.
+     */
+    public boolean isScrollable() {
+        return getBooleanProperty(PROPERTY_SCROLLABLE);
+    }
+
+    /**
+     * Sets if the node is scrollable.
+     *
+     * @param scrollable True if the node is scrollable, false otherwise.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setScrollable(boolean scrollable) {
+        enforceNotSealed();
+        setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+    }
+
+    /**
      * Gets the package this node comes from.
      *
      * @return The package name.
@@ -1017,6 +1040,7 @@
         builder.append("; longClickable: ").append(isLongClickable());
         builder.append("; enabled: ").append(isEnabled());
         builder.append("; password: ").append(isPassword());
+        builder.append("; scrollable: " + isScrollable());
 
         builder.append("; [");
 
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 9c495e21..b9815c5 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -40,6 +40,7 @@
     private static final int PROPERTY_ENABLED = 0x00000002;
     private static final int PROPERTY_PASSWORD = 0x00000004;
     private static final int PROPERTY_FULL_SCREEN = 0x00000080;
+    private static final int PROPERTY_SCROLLABLE = 0x00000100;
 
     // Housekeeping
     private static final int MAX_POOL_SIZE = 10;
@@ -54,6 +55,10 @@
     int mCurrentItemIndex;
     int mItemCount;
     int mFromIndex;
+    int mToIndex;
+    int mScrollX;
+    int mScrollY;
+
     int mAddedCount;
     int mRemovedCount;
     int mSourceViewId = View.NO_ID;
@@ -71,7 +76,6 @@
      * Hide constructor.
      */
     AccessibilityRecord() {
-
     }
 
     /**
@@ -85,6 +89,9 @@
         mCurrentItemIndex = record.mCurrentItemIndex;
         mItemCount = record.mItemCount;
         mFromIndex = record.mFromIndex;
+        mToIndex = record.mToIndex;
+        mScrollX = record.mScrollX;
+        mScrollY = record.mScrollY;
         mAddedCount = record.mAddedCount;
         mRemovedCount = record.mRemovedCount;
         mClassName = record.mClassName;
@@ -246,6 +253,27 @@
     }
 
     /**
+     * Gets if the source is scrollable.
+     *
+     * @return True if the source is scrollable, false otherwise.
+     */
+    public boolean isScrollable() {
+        return getBooleanProperty(PROPERTY_SCROLLABLE);
+    }
+
+    /**
+     * Sets if the source is scrollable.
+     *
+     * @param scrollable True if the source is scrollable, false otherwise.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setScrollable(boolean scrollable) {
+        enforceNotSealed();
+        setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+    }
+
+    /**
      * Gets the number of items that can be visited.
      *
      * @return The number of items.
@@ -288,18 +316,24 @@
     }
 
     /**
-     * Gets the index of the first character of the changed sequence.
+     * Gets the index of the first character of the changed sequence,
+     * or the beginning of a text selection or the index of the first
+     * visible item when scrolling.
      *
-     * @return The index of the first character.
+     * @return The index of the first character or selection
+     *        start or the first visible item.
      */
     public int getFromIndex() {
         return mFromIndex;
     }
 
     /**
-     * Sets the index of the first character of the changed sequence.
+     * Sets the index of the first character of the changed sequence
+     * or the beginning of a text selection or the index of the first
+     * visible item when scrolling.
      *
-     * @param fromIndex The index of the first character.
+     * @param fromIndex The index of the first character or selection
+     *        start or the first visible item.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
      */
@@ -309,6 +343,65 @@
     }
 
     /**
+     * Gets the index of text selection end or the index of the last
+     * visible item when scrolling.
+     *
+     * @return The index of selection end or last item index.
+     */
+    public int getToIndex() {
+        return mToIndex;
+    }
+
+    /**
+     * Sets the index of text selection end or the index of the last
+     * visible item when scrolling.
+     *
+     * @param toIndex The index of selection end or last item index.
+     */
+    public void setToIndex(int toIndex) {
+        enforceNotSealed();
+        mToIndex = toIndex;
+    }
+
+    /**
+     * Gets the scroll position of the source along the X axis.
+     *
+     * @return The scroll along the X axis.
+     */
+    public int getScrollX() {
+        return mScrollX;
+    }
+
+    /**
+     * Sets the scroll position of the source along the X axis.
+     *
+     * @param scrollX The scroll along the X axis.
+     */
+    public void setScrollX(int scrollX) {
+        enforceNotSealed();
+        mScrollX = scrollX;
+    }
+
+    /**
+     * Gets the scroll position of the source along the Y axis.
+     *
+     * @return The scroll along the Y axis.
+     */
+    public int getScrollY() {
+        return mScrollY;
+    }
+
+    /**
+     * Sets the scroll position of the source along the Y axis.
+     *
+     * @param scrollY The scroll along the Y axis.
+     */
+    public void setScrollY(int scrollY) {
+        enforceNotSealed();
+        mScrollY = scrollY;
+    }
+
+    /**
      * Gets the number of added characters.
      *
      * @return The number of added characters.
@@ -576,6 +669,9 @@
         mCurrentItemIndex = INVALID_POSITION;
         mItemCount = 0;
         mFromIndex = 0;
+        mToIndex = 0;
+        mScrollX = 0;
+        mScrollY = 0;
         mAddedCount = 0;
         mRemovedCount = 0;
         mClassName = null;
@@ -599,8 +695,12 @@
         builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
         builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
         builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
+        builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
         builder.append("; BeforeText: " + mBeforeText);
         builder.append("; FromIndex: " + mFromIndex);
+        builder.append("; ToIndex: " + mToIndex);
+        builder.append("; ScrollX: " + mScrollX);
+        builder.append("; ScrollY: " + mScrollY);
         builder.append("; AddedCount: " + mAddedCount);
         builder.append("; RemovedCount: " + mRemovedCount);
         builder.append("; ParcelableData: " + mParcelableData);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 47f5e4c..a1a7281 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1126,7 +1126,7 @@
         if (mServedView == mNextServedView && !mNextServedNeedsStart) {
             return;
         }
-        
+
         InputConnection ic = null;
         synchronized (mH) {
             if (mServedView == mNextServedView && !mNextServedNeedsStart) {
@@ -1242,6 +1242,27 @@
     }
 
     /**
+     * Notify the event when the user tapped or clicked the text view.
+     */
+    public void viewClicked(View view) {
+        final boolean focusChanged = mServedView != mNextServedView;
+        checkFocus();
+        synchronized (mH) {
+            if ((mServedView != view && (mServedView == null
+                    || !mServedView.checkInputConnectionProxy(view)))
+                    || mCurrentTextBoxAttribute == null || mCurMethod == null) {
+                return;
+            }
+            try {
+                if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
+                mCurMethod.viewClicked(focusChanged);
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+            }
+        }
+    }
+
+    /**
      * Returns true if the current input method wants to watch the location
      * of the input editor's cursor in its window.
      */
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index bb03afa..ea6f5ee 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -63,6 +63,15 @@
             int candidatesStart, int candidatesEnd);
 
     /**
+     * This method is called when the user tapped a text view.
+     * IMEs can't rely on this method being called because this was not part of the original IME
+     * protocol, so applications with custom text editing written before this method appeared will
+     * not call to inform the IME of this interaction.
+     * @param focusChanged true if the user changed the focused view by this click.
+     */
+    public void viewClicked(boolean focusChanged);
+
+    /**
      * This method is called when cursor location of the target input field
      * has changed within its window.  This is not normally called, but will
      * only be reported if requested by the input method.
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 2f4774f..79a5aff 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1150,11 +1150,12 @@
      * {@link #nativeSslCertErrorProceed(int)} or
      * {@link #nativeSslCertErrorCancel(int, int)}.
      */
-    private void reportSslCertError(final int handle, final int cert_error, byte cert_der[]) {
+    private void reportSslCertError(
+            final int handle, final int cert_error, byte cert_der[], String url) {
         final SslError ssl_error;
         try {
             X509Certificate cert = new X509CertImpl(cert_der);
-            ssl_error = new SslError(cert_error, cert);
+            ssl_error = new SslError(cert_error, cert, url);
         } catch (IOException e) {
             // Can't get the certificate, not much to do.
             Log.e(LOGTAG, "Can't get the certificate from WebKit, canceling");
diff --git a/core/java/android/webkit/CertTool.java b/core/java/android/webkit/CertTool.java
index 4c534f9..a2325c3 100644
--- a/core/java/android/webkit/CertTool.java
+++ b/core/java/android/webkit/CertTool.java
@@ -21,31 +21,27 @@
 import com.android.org.bouncycastle.jce.netscape.NetscapeCertRequest;
 import com.android.org.bouncycastle.util.encoders.Base64;
 
-import android.content.ActivityNotFoundException;
 import android.content.Context;
-import android.content.Intent;
 import android.security.Credentials;
+import android.security.KeyChain;
 import android.util.Log;
 
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.util.HashMap;
 
-class CertTool {
+final class CertTool {
     private static final String LOGTAG = "CertTool";
 
     private static final AlgorithmIdentifier MD5_WITH_RSA =
             new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);
 
-    static final String CERT = Credentials.CERTIFICATE;
-    static final String PKCS12 = Credentials.PKCS12;
-
     private static HashMap<String, String> sCertificateTypeMap;
     static {
         sCertificateTypeMap = new HashMap<String, String>();
-        sCertificateTypeMap.put("application/x-x509-ca-cert", CertTool.CERT);
-        sCertificateTypeMap.put("application/x-x509-user-cert", CertTool.CERT);
-        sCertificateTypeMap.put("application/x-pkcs12", CertTool.PKCS12);
+        sCertificateTypeMap.put("application/x-x509-ca-cert", KeyChain.EXTRA_CERTIFICATE);
+        sCertificateTypeMap.put("application/x-x509-user-cert", KeyChain.EXTRA_CERTIFICATE);
+        sCertificateTypeMap.put("application/x-pkcs12", KeyChain.EXTRA_PKCS12);
     }
 
     static String[] getKeyStrengthList() {
@@ -77,7 +73,7 @@
 
     static String getCertType(String mimeType) {
         return sCertificateTypeMap.get(mimeType);
-  }
+    }
 
     private CertTool() {}
 }
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 4cae9d8..11ab0d7 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -104,9 +104,13 @@
 
         public void surfaceDestroyed(SurfaceHolder holder)
         {
-            // after we return from this we can't use the surface any more
-            mSurfaceHolder = null;
+            // 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.
+            pauseAndDispatch(mProxy);
+            mSurfaceHolder = null;
+            if (mMediaController != null) {
+                mMediaController.hide();
+            }
         }
     };
 
@@ -210,7 +214,6 @@
                 // which happens when the video view is detached from its parent
                 // view. This happens in the WebChromeClient before this method
                 // is invoked.
-                pauseAndDispatch(mProxy);
                 mProxy.dispatchOnStopFullScreen();
                 mLayout.removeView(getSurfaceView());
 
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index b5d4933..bb4d192 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -23,6 +23,10 @@
 import java.io.InputStream;
 
 class JniUtil {
+
+    static {
+        System.loadLibrary("webcore");
+    }
     private static final String LOGTAG = "webkit";
     private JniUtil() {} // Utility class, do not instantiate.
 
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 06a61bd..7e41d36 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2000,8 +2000,12 @@
         if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
         draw.mBaseLayer = nativeRecordContent(draw.mInvalRegion, draw.mContentSize);
         if (draw.mBaseLayer == 0) {
-            if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
-            mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+            if (mWebView != null && !mWebView.isPaused()) {
+                if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
+                mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+            } else {
+                if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, webview paused");
+            }
             return;
         }
         webkitDraw(draw);
@@ -2358,7 +2362,7 @@
                 mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
                         mViewportInitialScale / 100.0f;
             } else if (mViewportWidth > 0 && mViewportWidth < webViewWidth &&
-                !mWebView.getSettings().getUseFixedViewport()) {
+                !getSettings().getUseFixedViewport()) {
                 mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
                         (float) webViewWidth / mViewportWidth;
             } else {
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 883656b..6c6974b 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -1107,7 +1107,8 @@
                 }
                 reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
             }
-            mInitialZoomOverview = !exceedsMinScaleIncrement(scale, overviewScale);
+            mInitialZoomOverview = settings.getLoadWithOverviewMode() &&
+                    !exceedsMinScaleIncrement(scale, overviewScale);
             setZoomScale(scale, reflowText);
 
             // update the zoom buttons as the scale can be changed
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3fe8149..1449b18 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -55,6 +55,8 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -1257,6 +1259,33 @@
         onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            event.setFromIndex(mFirstPosition);
+            event.setToIndex(mFirstPosition +  getChildCount());
+            event.setItemCount(mItemCount);
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     /**
      * Indicates whether the children's drawing cache is used during a scroll.
      * By default, the drawing cache is enabled but this will consume more memory.
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index ce76bee..0ffd087 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -34,6 +34,8 @@
 import android.view.ViewGroup;
 import android.view.SoundEffectConstants;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Transformation;
 
 /**
@@ -344,7 +346,34 @@
     int getChildHeight(View child) {
         return child.getMeasuredHeight();
     }
-    
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            event.setFromIndex(mFirstPosition);
+            event.setToIndex(mFirstPosition +  getChildCount());
+            event.setItemCount(mItemCount);
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     /**
      * Tracks a motion scroll. In reality, this is used to do just about any
      * movement to items (touch scroll, arrow-key scroll, set an item as selected).
@@ -382,7 +411,9 @@
         mRecycler.clear();
         
         setSelectionToCenterChild();
-        
+
+        onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+
         invalidate();
     }
 
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 0e52869..1570224 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -535,7 +535,7 @@
         return result;
     }
 
-    private int getDefaultMargin(View c, boolean leading, boolean horizontal) {
+    private int getDefaultMargin(View c, boolean horizontal, boolean leading) {
         // In the absence of any other information, calculate a default gap such
         // that, in a grid of identical components, the heights and the vertical
         // gaps are in the proportion of the golden ratio.
@@ -544,12 +544,12 @@
         return (int) (c.getMeasuredHeight() / GOLDEN_RATIO / 2);
     }
 
-    private int getDefaultMargin(View c, boolean isAtEdge, boolean leading, boolean horizontal) {
+    private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
         // todo remove DEFAULT_CONTAINER_MARGIN. Use padding? Seek advice on Themes/Styles, etc.
-        return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, leading, horizontal);
+        return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
     }
 
-    private int getDefaultMarginValue(View c, LayoutParams p, boolean leading, boolean horizontal) {
+    private int getDefaultMarginValue(View c, LayoutParams p, boolean horizontal, boolean leading) {
         if (!mUseDefaultMargins) {
             return 0;
         }
@@ -558,15 +558,19 @@
         Interval span = group.span;
         boolean isAtEdge = leading ? (span.min == 0) : (span.max == axis.getCount());
 
-        return getDefaultMargin(c, isAtEdge, leading, horizontal);
+        return getDefaultMargin(c, isAtEdge, horizontal, leading);
     }
 
-    private int getMargin(View view, boolean leading, boolean horizontal) {
+    private int getMargin(View view, boolean horizontal, boolean leading) {
         LayoutParams lp = getLayoutParams(view);
         int margin = horizontal ?
                 (leading ? lp.leftMargin : lp.rightMargin) :
                 (leading ? lp.topMargin : lp.bottomMargin);
-        return margin == UNDEFINED ? getDefaultMarginValue(view, lp, leading, horizontal) : margin;
+        return margin == UNDEFINED ? getDefaultMarginValue(view, lp, horizontal, leading) : margin;
+    }
+
+    private int getTotalMargin(View child, boolean horizontal) {
+        return getMargin(child, horizontal, true) + getMargin(child, horizontal, false);
     }
 
     private static int valueIfDefined(int value, int defaultValue) {
@@ -749,8 +753,8 @@
                 View c = getChildAt(i);
                 drawRectangle(canvas,
                         c.getLeft() - getMargin(c, true, true),
-                        c.getTop() - getMargin(c, true, false),
-                        c.getRight() + getMargin(c, false, true),
+                        c.getTop() - getMargin(c, false, true),
+                        c.getRight() + getMargin(c, true, false),
                         c.getBottom() + getMargin(c, false, false), paint);
             }
         }
@@ -794,17 +798,12 @@
         return c.getVisibility() == View.GONE;
     }
 
-    private void measureChildWithMargins(View child,
-            int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
-
+    private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) {
         LayoutParams lp = getLayoutParams(child);
-        int hMargins = getMargin(child, true, true) + getMargin(child, false, true);
-        int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
-                mPaddingLeft + mPaddingRight + hMargins, lp.width);
-        int vMargins = getMargin(child, true, false) + getMargin(child, false, false);
-        int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
-                mPaddingTop + mPaddingBottom + vMargins, lp.height);
-
+        int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+                mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width);
+        int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+                mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height);
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
 
@@ -842,9 +841,7 @@
     private int getMeasurementIncludingMargin(View c, boolean horizontal, int measurementType) {
         int result = getMeasurement(c, horizontal, measurementType);
         if (mAlignmentMode == ALIGN_MARGINS) {
-            int leadingMargin = getMargin(c, true, horizontal);
-            int trailingMargin = getMargin(c, false, horizontal);
-            return result + leadingMargin + trailingMargin;
+            return result + getTotalMargin(c, horizontal);
         }
         return result;
     }
@@ -919,8 +916,8 @@
 
             if (mAlignmentMode == ALIGN_MARGINS) {
                 int leftMargin = getMargin(c, true, true);
-                int topMargin = getMargin(c, true, false);
-                int rightMargin = getMargin(c, false, true);
+                int topMargin = getMargin(c, false, true);
+                int rightMargin = getMargin(c, true, false);
                 int bottomMargin = getMargin(c, false, false);
 
                 // Same calculation as getMeasurementIncludingMargin()
@@ -928,8 +925,8 @@
                 int mHeight = topMargin + pHeight + bottomMargin;
 
                 // Alignment offsets: the location of the view relative to its alignment group.
-                int a2vx = colBounds.before - hAlign.getAlignmentValue(c, mWidth, type);
-                int a2vy = rowBounds.before - vAlign.getAlignmentValue(c, mHeight, type);
+                int a2vx = colBounds.getOffset(c, hAlign, type, mWidth);
+                int a2vy = rowBounds.getOffset(c, vAlign, type, mHeight);
 
                 dx = c2ax + a2vx + leftMargin;
                 dy = c2ay + a2vy + topMargin;
@@ -938,8 +935,8 @@
                 cellHeight -= topMargin + bottomMargin;
             } else {
                 // Alignment offsets: the location of the view relative to its alignment group.
-                int a2vx = colBounds.before - hAlign.getAlignmentValue(c, pWidth, type);
-                int a2vy = rowBounds.before - vAlign.getAlignmentValue(c, pHeight, type);
+                int a2vx = colBounds.getOffset(c, hAlign, type, pWidth);
+                int a2vy = rowBounds.getOffset(c, vAlign, type, pHeight);
 
                 dx = c2ax + a2vx;
                 dy = c2ay + a2vy;
@@ -1051,7 +1048,7 @@
                 Group group = horizontal ? lp.columnGroup : lp.rowGroup;
 
                 groups[i] = group;
-                bounds[i] = new Bounds();
+                bounds[i] = group.alignment.getBounds();
             }
 
             return new PackedMap<Group, Bounds>(groups, bounds);
@@ -1387,7 +1384,7 @@
                 Group g = horizontal ? lp.columnGroup : lp.rowGroup;
                 Interval span = g.span;
                 int index = leading ? span.min : span.max;
-                margins[index] = max(margins[index], getMargin(c, leading, horizontal));
+                margins[index] = max(margins[index], getMargin(c, horizontal, leading));
             }
         }
 
@@ -1817,7 +1814,8 @@
         }
 
         private int getDefaultWeight(int size) {
-            return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
+            //return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
+            return DEFAULT_WEIGHT_0;
         }
 
         private void init(Context context, AttributeSet attrs, int defaultGravity) {
@@ -1996,20 +1994,24 @@
             reset();
         }
 
-        private void reset() {
+        protected void reset() {
             before = Integer.MIN_VALUE;
             after = Integer.MIN_VALUE;
         }
 
-        private void include(int before, int after) {
+        protected void include(int before, int after) {
             this.before = max(this.before, before);
             this.after = max(this.after, after);
         }
 
-        private int size() {
+        protected int size() {
             return before + after;
         }
 
+        protected int getOffset(View c, Alignment alignment, int type, int size) {
+            return before - alignment.getAlignmentValue(c, size, type);
+        }
+
         @Override
         public String toString() {
             return "Bounds{" +
@@ -2235,15 +2237,18 @@
      * {@link Group#alignment alignment}. Overall placement of the view in the cell
      * group is specified by the two alignments which act along each axis independently.
      * <p>
+     *  The GridLayout class defines the most common alignments used in general layout:
+     * {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, {@link #RIGHT}, {@link #CENTER}, {@link
+     * #BASELINE} and {@link #FILL}.
+     */
+    /*
      * An Alignment implementation must define {@link #getAlignmentValue(View, int, int)},
      * to return the appropriate value for the type of alignment being defined.
      * The enclosing algorithms position the children
      * so that the locations defined by the alignment values
      * are the same for all of the views in a group.
      * <p>
-     *  The GridLayout class defines the most common alignments used in general layout:
-     * {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, {@link #RIGHT}, {@link #CENTER}, {@link
-     * #BASELINE} and {@link #FILL}.
+
      */
     public static abstract class Alignment {
         private static final Alignment GONE = new Alignment() {
@@ -2253,6 +2258,9 @@
             }
         };
 
+        /*pp*/ Alignment() {
+        }
+
         /**
          * Returns an alignment value. In the case of vertical alignments the value
          * returned should indicate the distance from the top of the view to the
@@ -2266,7 +2274,7 @@
          *
          * @return the alignment value
          */
-        public abstract int getAlignmentValue(View view, int viewSize, int measurementType);
+        /*pp*/ abstract int getAlignmentValue(View view, int viewSize, int measurementType);
 
         /**
          * Returns the size of the view specified by this alignment.
@@ -2283,9 +2291,13 @@
          *
          * @return the aligned size
          */
-        public int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) {
+        /*pp*/ int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) {
             return viewSize;
         }
+
+        /*pp*/ Bounds getBounds() {
+            return new Bounds();
+        }
     }
 
     private static final Alignment LEADING = new Alignment() {
@@ -2349,11 +2361,42 @@
                 return UNDEFINED;
             }
             int baseline = view.getBaseline();
-            if (baseline == -1) {
-                return UNDEFINED;
-            } else {
-                return baseline;
-            }
+            return (baseline == -1) ? UNDEFINED : baseline;
+        }
+
+        @Override
+        public Bounds getBounds() {
+            return new Bounds() {
+                /*
+                In a baseline aligned row in which some components define a baseline
+                and some don't, we need a third variable to properly account for all
+                the sizes. This tracks the maximum size of all the components -
+                including those that don't define a baseline.
+                */
+                private int size;
+
+                @Override
+                protected void reset() {
+                    super.reset();
+                    size = 0;
+                }
+
+                @Override
+                protected void include(int before, int after) {
+                    super.include(before, after);
+                    size = max(size, before + after);
+                }
+
+                @Override
+                protected int size() {
+                    return max(super.size(), size);
+                }
+
+                @Override
+                protected int getOffset(View c, Alignment alignment, int type, int size) {
+                    return max(0, super.getOffset(c, alignment, type, size));
+                }
+            };
         }
     };
 
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 17b3bda..7c9be1e 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -35,6 +35,8 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 
 import java.util.List;
@@ -692,6 +694,28 @@
         awakenScrollBars();
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     private int getScrollRange() {
         int scrollRange = 0;
         if (getChildCount() > 0) {
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 2947ebe..aa23ad0 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1201,18 +1201,15 @@
     private void initializeScrollWheel() {
         if (mInitialScrollOffset != Integer.MIN_VALUE) {
             return;
-
         }
         int[] selectorIndices = getSelectorIndices();
         int totalTextHeight = selectorIndices.length * mTextSize;
-        int totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
-        int textGapCount = selectorIndices.length - 1;
-        int selectorTextGapHeight = totalTextGapHeight / textGapCount;
-        // compensate for integer division loss of the components used to
-        // calculate the text gap
-        int integerDivisionLoss = (mTextSize + mBottom - mTop) % textGapCount;
-        mInitialScrollOffset = mCurrentScrollOffset = mTextSize - integerDivisionLoss / 2;
+        float totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
+        float textGapCount = selectorIndices.length - 1;
+        int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f);
         mSelectorElementHeight = mTextSize + selectorTextGapHeight;
+        mInitialScrollOffset = mTextSize - 3 * (mSelectorElementHeight % 2);
+        mCurrentScrollOffset = mInitialScrollOffset;
         updateInputTextView();
     }
 
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 27edb88..12775a4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -36,6 +36,8 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 
 import java.util.List;
@@ -690,6 +692,28 @@
         awakenScrollBars();
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     private int getScrollRange() {
         int scrollRange = 0;
         if (getChildCount() > 0) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 586ece8..f3bda43 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -603,7 +603,7 @@
         final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
         // Should we show the close button? It is not shown if there's no focus,
         // field is not iconified by default and there is no text in it.
-        final boolean showClose = hasText || mIconifiedByDefault || mQueryTextView.hasFocus();
+        final boolean showClose = hasText || mIconifiedByDefault;
         mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE);
         mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
     }
@@ -919,17 +919,22 @@
     }
 
     private void onCloseClicked() {
-        if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
-            CharSequence text = mQueryTextView.getText();
-            if (TextUtils.isEmpty(text)) {
+        CharSequence text = mQueryTextView.getText();
+        if (TextUtils.isEmpty(text)) {
+            if (mIconifiedByDefault) {
                 // query field already empty, hide the keyboard and remove focus
                 clearFocus();
                 setImeVisibility(false);
-            } else {
-                mQueryTextView.setText("");
             }
+        } else {
+            mQueryTextView.setText("");
+            mQueryTextView.requestFocus();
+            setImeVisibility(true);
+        }
+
+        if (mIconifiedByDefault && (mOnCloseListener == null || !mOnCloseListener.onClose())) {
             updateViewsVisibility(mIconifiedByDefault);
-            if (mIconifiedByDefault) setImeVisibility(false);
+            setImeVisibility(false);
         }
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 77df7c8..2a70ac8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4948,7 +4948,10 @@
                         if (mMovement != null && mText instanceof Editable
                                 && mLayout != null && onCheckIsTextEditor()) {
                             InputMethodManager imm = InputMethodManager.peekInstance();
-                            if (imm != null) imm.showSoftInput(this, 0);
+                            if (imm != null) {
+                                imm.viewClicked(this);
+                                imm.showSoftInput(this, 0);
+                            }
                         }
                     }
                 }
@@ -6834,9 +6837,9 @@
      * @param selEnd The new selection end location.
      */
     protected void onSelectionChanged(int selStart, int selEnd) {
-        // intentionally empty
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
     }
-    
+
     /**
      * Adds a TextWatcher to the list of those whose methods are called
      * whenever this TextView's text changes.
@@ -7398,8 +7401,11 @@
 
             if ((isTextEditable() || mTextIsSelectable) && touchIsFinished) {
                 // Show the IME, except when selecting in read-only text.
+                final InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    imm.viewClicked(this);
+                }
                 if (!mTextIsSelectable) {
-                    final InputMethodManager imm = InputMethodManager.peekInstance();
                     handled |= imm != null && imm.showSoftInput(this, 0);
                 }
 
@@ -7668,7 +7674,7 @@
         }
         String searchedLowerCase = searched.toString().toLowerCase();
         String thisTextLowerCase = thisText.toString().toLowerCase();
-        if (thisTextLowerCase.contains(searched)) {
+        if (thisTextLowerCase.contains(searchedLowerCase)) {
             outViews.add(this);
         }
     }
@@ -7922,6 +7928,12 @@
 
         final boolean isPassword = hasPasswordTransformationMethod();
         event.setPassword(isPassword);
+
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
+            event.setFromIndex(Selection.getSelectionStart(mText));
+            event.setToIndex(Selection.getSelectionEnd(mText));
+            event.setItemCount(mText.length());
+        }
     }
 
     @Override
@@ -10004,6 +10016,127 @@
         return mInBatchEditControllers;
     }
 
+    /**
+     * Resolve the text direction.
+     *
+     * Text direction of paragraphs in a TextView is determined using a heuristic. If the correct
+     * text direction cannot be determined by the heuristic, the view’s resolved layout direction
+     * determines the direction.
+     *
+     * This heuristic and result is applied individually to each paragraph in a TextView, based on
+     * the text and style content of that paragraph. Paragraph text styles can also be used to force
+     * a particular direction.
+     */
+    @Override
+    protected void resolveTextDirection() {
+        int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+        switch(mTextDirection) {
+            default:
+            case TEXT_DIRECTION_INHERIT:
+                // Try to the text direction from the parent layout. If not possible, then we will
+                // use the default layout direction to decide later
+                if (mParent != null && mParent instanceof ViewGroup) {
+                    resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+                }
+                break;
+            case TEXT_DIRECTION_FIRST_STRONG:
+                resolvedTextDirection = getTextDirectionFromFirstStrong(mText);
+                break;
+            case TEXT_DIRECTION_ANY_RTL:
+                resolvedTextDirection = getTextDirectionFromAnyRtl(mText);
+                break;
+            case TEXT_DIRECTION_LTR:
+                resolvedTextDirection = TEXT_DIRECTION_LTR;
+                break;
+            case TEXT_DIRECTION_RTL:
+                resolvedTextDirection = TEXT_DIRECTION_RTL;
+                break;
+        }
+        // if we have been so far unable to get the text direction from the heuristics, then we are
+        // falling back using the layout direction
+        if (resolvedTextDirection == TEXT_DIRECTION_UNDEFINED) {
+            switch(getResolvedLayoutDirection()) {
+                default:
+                case LAYOUT_DIRECTION_LTR:
+                    resolvedTextDirection = TEXT_DIRECTION_LTR;
+                    break;
+                case LAYOUT_DIRECTION_RTL:
+                    resolvedTextDirection = TEXT_DIRECTION_RTL;
+                    break;
+            }
+        }
+        mResolvedTextDirection = resolvedTextDirection;
+    }
+
+    /**
+     * Get text direction following the "first strong" heuristic.
+     *
+     * @param cs the CharSequence used to get the text direction.
+     *
+     * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+     * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+     */
+    private static int getTextDirectionFromFirstStrong(final CharSequence cs) {
+        final int length = cs.length();
+        for(int i = 0; i < length; i++) {
+            final char c = cs.charAt(i);
+            final byte dir = Character.getDirectionality(c);
+            if (isStrongLtrChar(dir)) {
+                return TEXT_DIRECTION_LTR;
+            } else if (isStrongRtlChar(dir)) {
+                return TEXT_DIRECTION_RTL;
+            }
+        }
+        return TEXT_DIRECTION_UNDEFINED;
+    }
+
+    /**
+     * Get text direction following the "any RTL" heuristic.
+     *
+     * @param cs the CharSequence used to get the text direction.
+     *
+     * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+     * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+     */
+    private static int getTextDirectionFromAnyRtl(final CharSequence cs) {
+        final int length = cs.length();
+        boolean foundStrongLtr = false;
+        boolean foundStrongRtl = false;
+        for(int i = 0; i < length; i++) {
+            final char c = cs.charAt(i);
+            final byte dir = Character.getDirectionality(c);
+            if (isStrongLtrChar(dir)) {
+                foundStrongLtr = true;
+            } else if (isStrongRtlChar(dir)) {
+                foundStrongRtl = true;
+            }
+        }
+        if (foundStrongRtl) {
+            return TEXT_DIRECTION_RTL;
+        }
+        if (foundStrongLtr) {
+            return TEXT_DIRECTION_LTR;
+        }
+        return TEXT_DIRECTION_UNDEFINED;
+    }
+
+    /**
+     * Return true if the char direction is corresponding to a "strong RTL char" following the
+     * Unicode Bidirectional Algorithm (UBA).
+     */
+    private static boolean isStrongRtlChar(final byte dir) {
+        return (dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
+                dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC);
+    }
+
+    /**
+     * Return true if the char direction is corresponding to a "strong LTR char" following the
+     * Unicode Bidirectional Algorithm (UBA).
+     */
+    private static boolean isStrongLtrChar(final byte dir) {
+        return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT);
+    }
+
     @ViewDebug.ExportedProperty(category = "text")
     private CharSequence            mText;
     private CharSequence            mTransformed;
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index b57046c..ec64552 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -135,6 +135,16 @@
         return null;
    }
 
+   public static String getSdFilesystem(String cid) {
+       try {
+            return getMountService().getSecureContainerFilesystemPath(cid);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get container path for " + cid +
+                " with exception " + e);
+        }
+        return null;
+   }
+
     public static boolean finalizeSdDir(String cid) {
         try {
             int rc = getMountService().finalizeSecureContainer(cid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 12687a1..7b65964 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,6 +41,7 @@
 import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TimeUtils;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -4870,8 +4871,8 @@
         return 0;
     }
 
-    void readHistory(Parcel in) {
-        mHistoryBaseTime = in.readLong();
+    void readHistory(Parcel in, boolean andOldHistory) {
+        final long historyBaseTime = in.readLong();
 
         mHistoryBuffer.setDataSize(0);
         mHistoryBuffer.setDataPosition(0);
@@ -4889,15 +4890,35 @@
             in.setDataPosition(curPos + bufSize);
         }
 
-        long oldnow = SystemClock.elapsedRealtime() - (5*60*1000);
-        if (oldnow > 0) {
-            // If the system process has restarted, but not the entire
-            // system, then the mHistoryBaseTime already accounts for
-            // much of the elapsed time.  We thus want to adjust it back,
-            // to avoid large gaps in the data.  We determine we are
-            // in this case by arbitrarily saying it is so if at this
-            // point in boot the elapsed time is already more than 5 minutes.
-            mHistoryBaseTime -= oldnow;
+        if (andOldHistory) {
+            readOldHistory(in);
+        }
+
+        if (DEBUG_HISTORY) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("****************** OLD mHistoryBaseTime: ");
+            TimeUtils.formatDuration(mHistoryBaseTime, sb);
+            Slog.i(TAG, sb.toString());
+        }
+        mHistoryBaseTime = historyBaseTime;
+        if (DEBUG_HISTORY) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("****************** NEW mHistoryBaseTime: ");
+            TimeUtils.formatDuration(mHistoryBaseTime, sb);
+            Slog.i(TAG, sb.toString());
+        }
+
+        // We are just arbitrarily going to insert 1 minute from the sample of
+        // the last run until samples in this run.
+        if (mHistoryBaseTime > 0) {
+            long oldnow = SystemClock.elapsedRealtime();
+            mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
+            if (DEBUG_HISTORY) {
+                StringBuilder sb = new StringBuilder(128);
+                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
+                TimeUtils.formatDuration(mHistoryBaseTime, sb);
+                Slog.i(TAG, sb.toString());
+            }
         }
     }
 
@@ -4910,12 +4931,24 @@
         }
     }
 
-    void writeHistory(Parcel out) {
-        out.writeLong(mLastHistoryTime);
+    void writeHistory(Parcel out, boolean andOldHistory) {
+        if (DEBUG_HISTORY) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("****************** WRITING mHistoryBaseTime: ");
+            TimeUtils.formatDuration(mHistoryBaseTime, sb);
+            sb.append(" mLastHistoryTime: ");
+            TimeUtils.formatDuration(mLastHistoryTime, sb);
+            Slog.i(TAG, sb.toString());
+        }
+        out.writeLong(mHistoryBaseTime + mLastHistoryTime);
         out.writeInt(mHistoryBuffer.dataSize());
         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+
+        if (andOldHistory) {
+            writeOldHistory(out);
+        }
     }
 
     void writeOldHistory(Parcel out) {
@@ -4935,8 +4968,7 @@
             return;
         }
 
-        readHistory(in);
-        readOldHistory(in);
+        readHistory(in, true);
 
         mStartCount = in.readInt();
         mBatteryUptime = in.readLong();
@@ -5136,8 +5168,7 @@
 
         out.writeInt(VERSION);
 
-        writeHistory(out);
-        writeOldHistory(out);
+        writeHistory(out, true);
 
         out.writeInt(mStartCount);
         out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
@@ -5340,7 +5371,7 @@
             throw new ParcelFormatException("Bad magic number");
         }
 
-        readHistory(in);
+        readHistory(in, false);
 
         mStartCount = in.readInt();
         mBatteryUptime = in.readLong();
@@ -5461,7 +5492,7 @@
 
         out.writeInt(MAGIC);
 
-        writeHistory(out);
+        writeHistory(out, false);
 
         out.writeInt(mStartCount);
         out.writeLong(mBatteryUptime);
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 5e9cd23..f13e770 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -25,16 +25,13 @@
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
-
 import com.android.internal.logging.AndroidConfig;
-
+import com.android.server.NetworkManagementSocketTagger;
 import dalvik.system.VMRuntime;
-
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.logging.LogManager;
 import java.util.TimeZone;
-
+import java.util.logging.LogManager;
 import org.apache.harmony.luni.internal.util.TimezoneGetter;
 
 /**
@@ -129,6 +126,11 @@
         System.setProperty("http.agent", userAgent);
 
         /*
+         * Wire socket tagging to traffic stats.
+         */
+        NetworkManagementSocketTagger.install();
+
+        /*
          * If we're running in an emulator launched with "-trace", put the
          * VM into emulator trace profiling mode so that the user can hit
          * F9/F10 at any time to capture traces.  This has performance
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index 338dcaa..f875cbd 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -36,7 +36,9 @@
     void updateSelection(int oldSelStart, int oldSelEnd,
             int newSelStart, int newSelEnd,
             int candidatesStart, int candidatesEnd);
-    
+
+    void viewClicked(boolean focusChanged);
+
     void updateCursor(in Rect newCursor);
     
     void displayCompletions(in CompletionInfo[] completions);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index c475eff..8eb046e 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -648,7 +648,7 @@
             }
         }
     }
-    
+
     private void initTitle() {
         if (mTitleLayout == null) {
             LayoutInflater inflater = LayoutInflater.from(getContext());
@@ -742,8 +742,14 @@
         View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
 
         if (homeLayout.getVisibility() != GONE) {
-            homeLayout.measure(
-                    MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+            final LayoutParams lp = homeLayout.getLayoutParams();
+            int homeWidthSpec;
+            if (lp.width < 0) {
+                homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
+            } else {
+                homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+            }
+            homeLayout.measure(homeWidthSpec,
                     MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
             final int homeWidth = homeLayout.getMeasuredWidth();
             availableWidth = Math.max(0, availableWidth - homeWidth);
@@ -982,8 +988,8 @@
             int ypos = 0;
             switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
                 case Gravity.CENTER_VERTICAL:
-                    final int paddedTop = mTop + getPaddingTop();
-                    final int paddedBottom = mBottom - getPaddingBottom();
+                    final int paddedTop = getPaddingTop();
+                    final int paddedBottom = mBottom - mTop - getPaddingBottom();
                     ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
                     break;
                 case Gravity.TOP:
@@ -994,7 +1000,10 @@
                             - bottomMargin;
                     break;
             }
-            x += positionChild(customView, xpos, ypos, contentHeight);
+            final int customWidth = customView.getMeasuredWidth();
+            customView.layout(xpos, ypos, xpos + customWidth,
+                    ypos + customView.getMeasuredHeight());
+            x += customWidth;
         }
 
         if (mProgressView != null) {
@@ -1120,6 +1129,34 @@
             width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
             height = Math.max(height,
                     iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
+
+            final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+            final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+            final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+            final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+            switch (widthMode) {
+                case MeasureSpec.AT_MOST:
+                    width = Math.min(width, widthSize);
+                    break;
+                case MeasureSpec.EXACTLY:
+                    width = widthSize;
+                    break;
+                case MeasureSpec.UNSPECIFIED:
+                default:
+                    break;
+            }
+            switch (heightMode) {
+                case MeasureSpec.AT_MOST:
+                    height = Math.min(height, heightSize);
+                    break;
+                case MeasureSpec.EXACTLY:
+                    height = heightSize;
+                    break;
+                case MeasureSpec.UNSPECIFIED:
+                default:
+                    break;
+            }
             setMeasuredDimension(width, height);
         }
 
@@ -1127,13 +1164,14 @@
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
             final int vCenter = (b - t) / 2;
             int width = r - l;
+            int upOffset = 0;
             if (mUpView.getVisibility() != GONE) {
                 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
                 final int upHeight = mUpView.getMeasuredHeight();
                 final int upWidth = mUpView.getMeasuredWidth();
-                final int upTop = t + vCenter - upHeight / 2;
-                mUpView.layout(l, upTop, l + upWidth, upTop + upHeight);
-                final int upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
+                final int upTop = vCenter - upHeight / 2;
+                mUpView.layout(0, upTop, upWidth, upTop + upHeight);
+                upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
                 width -= upOffset;
                 l += upOffset;
             }
@@ -1141,8 +1179,8 @@
             final int iconHeight = mIconView.getMeasuredHeight();
             final int iconWidth = mIconView.getMeasuredWidth();
             final int hCenter = (r - l) / 2;
-            final int iconLeft = l + iconLp.leftMargin + hCenter - iconWidth / 2;
-            final int iconTop = t + iconLp.topMargin + vCenter - iconHeight / 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);
         }
     }
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index cbb110a..97bbe52 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -103,7 +103,8 @@
     private boolean mTactileFeedbackEnabled = true;
     private boolean mPatternInProgress = false;
 
-    private float mDiameterFactor = 0.5f;
+    private float mDiameterFactor = 0.10f; // TODO: move to attrs
+    private final int mStrokeAlpha = 128;
     private float mHitFactor = 0.6f;
 
     private float mSquareWidth;
@@ -133,6 +134,7 @@
     private final Matrix mArrowMatrix = new Matrix();
     private final Matrix mCircleMatrix = new Matrix();
 
+
     /**
      * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
      */
@@ -267,17 +269,17 @@
         mPathPaint.setAntiAlias(true);
         mPathPaint.setDither(true);
         mPathPaint.setColor(Color.WHITE);   // TODO this should be from the style
-        mPathPaint.setAlpha(128);
+        mPathPaint.setAlpha(mStrokeAlpha);
         mPathPaint.setStyle(Paint.Style.STROKE);
         mPathPaint.setStrokeJoin(Paint.Join.ROUND);
         mPathPaint.setStrokeCap(Paint.Cap.ROUND);
 
         // lot's of bitmaps!
-        mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default);
-        mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched);
-        mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default);
-        mBitmapCircleGreen = getBitmapFor(R.drawable.indicator_code_lock_point_area_green);
-        mBitmapCircleRed = getBitmapFor(R.drawable.indicator_code_lock_point_area_red);
+        mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_holo);
+        mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_holo);
+        mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default_holo);
+        mBitmapCircleGreen = getBitmapFor(R.drawable.indicator_code_lock_point_area_green_holo);
+        mBitmapCircleRed = getBitmapFor(R.drawable.indicator_code_lock_point_area_red_holo);
 
         mBitmapArrowGreenUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_green_up);
         mBitmapArrowRedUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_red_up);
@@ -464,8 +466,7 @@
                 break;
             case MeasureSpec.EXACTLY:
             default:
-                // use the specified size, if non-zero
-                result = specSize != 0 ? specSize : desired;
+                result = specSize;
         }
         return result;
     }
@@ -890,11 +891,48 @@
         final Path currentPath = mCurrentPath;
         currentPath.rewind();
 
+        // draw the circles
+        final int paddingTop = mPaddingTop;
+        final int paddingLeft = mPaddingLeft;
+
+        for (int i = 0; i < 3; i++) {
+            float topY = paddingTop + i * squareHeight;
+            //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
+            for (int j = 0; j < 3; j++) {
+                float leftX = paddingLeft + j * squareWidth;
+                drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
+            }
+        }
+
         // TODO: the path should be created and cached every time we hit-detect a cell
         // only the last segment of the path should be computed here
         // draw the path of the pattern (unless the user is in progress, and
         // we are in stealth mode)
         final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
+
+        // draw the arrows associated with the path (unless the user is in progress, and
+        // we are in stealth mode)
+        boolean oldFlag = (mPaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
+        mPaint.setFilterBitmap(true); // draw with higher quality since we render with transforms
+        if (drawPath) {
+            for (int i = 0; i < count - 1; i++) {
+                Cell cell = pattern.get(i);
+                Cell next = pattern.get(i + 1);
+
+                // only draw the part of the pattern stored in
+                // the lookup table (this is only different in the case
+                // of animation).
+                if (!drawLookup[next.row][next.column]) {
+                    break;
+                }
+
+                float leftX = paddingLeft + cell.column * squareWidth;
+                float topY = paddingTop + cell.row * squareHeight;
+
+                drawArrow(canvas, leftX, topY, cell, next);
+            }
+        }
+
         if (drawPath) {
             boolean anyCircles = false;
             for (int i = 0; i < count; i++) {
@@ -925,41 +963,6 @@
             canvas.drawPath(currentPath, mPathPaint);
         }
 
-        // draw the circles
-        final int paddingTop = mPaddingTop;
-        final int paddingLeft = mPaddingLeft;
-
-        for (int i = 0; i < 3; i++) {
-            float topY = paddingTop + i * squareHeight;
-            //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
-            for (int j = 0; j < 3; j++) {
-                float leftX = paddingLeft + j * squareWidth;
-                drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
-            }
-        }
-
-        // draw the arrows associated with the path (unless the user is in progress, and
-        // we are in stealth mode)
-        boolean oldFlag = (mPaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
-        mPaint.setFilterBitmap(true); // draw with higher quality since we render with transforms
-        if (drawPath) {
-            for (int i = 0; i < count - 1; i++) {
-                Cell cell = pattern.get(i);
-                Cell next = pattern.get(i + 1);
-
-                // only draw the part of the pattern stored in
-                // the lookup table (this is only different in the case
-                // of animation).
-                if (!drawLookup[next.row][next.column]) {
-                    break;
-                }
-
-                float leftX = paddingLeft + cell.column * squareWidth;
-                float topY = paddingTop + cell.row * squareHeight;
-
-                drawArrow(canvas, leftX, topY, cell, next);
-            }
-        }
         mPaint.setFilterBitmap(oldFlag); // restore default flag
     }
 
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 3e7b976..5b35104 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -224,8 +224,8 @@
 
     /**
      * Animation used to attract user's attention to the target button.
-     * Assumes mChevronDrawables is an a list with an even number of chevrons filled with left
-     * followed by right chevrons.
+     * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
+     * mFeedbackCount items in the order: left, right, top, bottom.
      */
     private void startChevronAnimation() {
         final float r = mHandleDrawable.getWidth() / 2;
@@ -442,6 +442,7 @@
         mHandleDrawable.setX(mWaveCenterX);
         mHandleDrawable.setY(mWaveCenterY);
         mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+        Tweener.reset();
     }
 
     @Override
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index 0cff00a..bc8a62f 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -18,25 +18,42 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
 
 import android.animation.Animator.AnimatorListener;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.util.Log;
 
 class Tweener {
     private static final String TAG = "Tweener";
+    private static final boolean DEBUG = false;
 
-    private Object object;
     ObjectAnimator animator;
     private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
 
-    public Tweener(Object obj, ObjectAnimator anim) {
-        object = obj;
+    public Tweener(ObjectAnimator anim) {
         animator = anim;
     }
 
+    private static void remove(Animator animator) {
+        Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
+        while (iter.hasNext()) {
+            Entry<Object, Tweener> entry = iter.next();
+            if (entry.getValue().animator == animator) {
+                if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
+                        + " sTweens.size() = " + sTweens.size());
+                iter.remove();
+                break; // an animator can only be attached to one object
+            }
+        }
+    }
+
     public static Tweener to(Object object, long duration, Object... vars) {
         long delay = 0;
         AnimatorUpdateListener updateListener = null;
@@ -77,32 +94,35 @@
 
         // Re-use existing tween, if present
         Tweener tween = sTweens.get(object);
+        ObjectAnimator anim = null;
         if (tween == null) {
-            ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(object,
+            anim = ObjectAnimator.ofPropertyValuesHolder(object,
                     props.toArray(new PropertyValuesHolder[props.size()]));
-            tween = new Tweener(object, anim);
+            tween = new Tweener(anim);
             sTweens.put(object, tween);
+            if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
         } else {
-            tween.animator.cancel();
-            replace(props, object);
+            anim = sTweens.get(object).animator;
+            replace(props, object); // Cancel all animators for given object
         }
 
         if (interpolator != null) {
-            tween.animator.setInterpolator(interpolator);
+            anim.setInterpolator(interpolator);
         }
 
         // Update animation with properties discovered in loop above
-        tween.animator.setStartDelay(delay);
-        tween.animator.setDuration(duration);
+        anim.setStartDelay(delay);
+        anim.setDuration(duration);
         if (updateListener != null) {
-            tween.animator.removeAllUpdateListeners(); // There should be only one
-            tween.animator.addUpdateListener(updateListener);
+            anim.removeAllUpdateListeners(); // There should be only one
+            anim.addUpdateListener(updateListener);
         }
         if (listener != null) {
-            tween.animator.removeAllListeners(); // There should be only one.
-            tween.animator.addListener(listener);
+            anim.removeAllListeners(); // There should be only one.
+            anim.addListener(listener);
         }
-        tween.animator.start();
+        anim.addListener(mCleanupListener);
+        anim.start();
 
         return tween;
     }
@@ -114,18 +134,40 @@
         return Tweener.to(object, duration, vars);
     }
 
-    static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
+    // Listener to watch for completed animations and remove them.
+    private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            remove(animation);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            remove(animation);
+        }
+    };
+
+    public static void reset() {
+        if (DEBUG) {
+            Log.v(TAG, "Reset()");
+            if (sTweens.size() > 0) {
+                Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
+            }
+        }
+        sTweens.clear();
+    }
+
+    private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
         for (final Object killobject : args) {
             Tweener tween = sTweens.get(killobject);
             if (tween != null) {
-                if (killobject == tween.object) {
-                    tween.animator.cancel();
-                    if (props != null) {
-                        tween.animator.setValues(
-                                props.toArray(new PropertyValuesHolder[props.size()]));
-                    } else {
-                        sTweens.remove(tween);
-                    }
+                tween.animator.cancel();
+                if (props != null) {
+                    tween.animator.setValues(
+                            props.toArray(new PropertyValuesHolder[props.size()]));
+                } else {
+                    sTweens.remove(tween);
                 }
             }
         }
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
new file mode 100644
index 0000000..306d223
--- /dev/null
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import dalvik.system.SocketTagger;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.SocketException;
+import java.nio.charset.Charsets;
+
+/**
+ * Assigns tags to sockets for traffic stats.
+ */
+public final class NetworkManagementSocketTagger extends SocketTagger {
+
+    private static final boolean LOGI = false;
+
+    private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
+        @Override protected SocketTags initialValue() {
+            return new SocketTags();
+        }
+    };
+
+    public static void install() {
+        SocketTagger.set(new NetworkManagementSocketTagger());
+    }
+
+    public static void setThreadSocketStatsTag(int tag) {
+        threadSocketTags.get().statsTag = tag;
+    }
+
+    public static void setThreadSocketStatsUid(int uid) {
+        threadSocketTags.get().statsUid = uid;
+    }
+
+    @Override public void tag(FileDescriptor fd) throws SocketException {
+        final SocketTags options = threadSocketTags.get();
+        if (LOGI) {
+            System.logI("tagSocket(" + fd.getInt$() + ") with statsTag="
+                    + options.statsTag + ", statsUid=" + options.statsUid);
+        }
+        try {
+            // TODO: skip tagging when options would be no-op
+            tagSocketFd(fd, options.statsTag, options.statsUid);
+        } catch (IOException e) {
+            throw new SocketException("Problem tagging socket", e);
+        }
+    }
+
+    private void tagSocketFd(FileDescriptor fd, int tag, int uid) throws IOException {
+        final int fdNum = fd.getInt$();
+        if (fdNum == -1 || (tag == -1 && uid == -1)) return;
+
+        String cmd = "t " + fdNum;
+        if (tag == -1) {
+            // Case where just the uid needs adjusting. But probably the caller
+            // will want to track his own name here, just in case.
+            cmd += " 0";
+        } else {
+            cmd += " " + tagToKernel(tag);
+        }
+        if (uid != -1) {
+            cmd += " " + uid;
+        }
+        internalModuleCtrl(cmd);
+    }
+
+    @Override public void untag(FileDescriptor fd) throws SocketException {
+        if (LOGI) {
+            System.logI("untagSocket(" + fd.getInt$() + ")");
+        }
+        try {
+            unTagSocketFd(fd);
+        } catch (IOException e) {
+            throw new SocketException("Problem untagging socket", e);
+        }
+    }
+
+    private void unTagSocketFd(FileDescriptor fd) throws IOException {
+        int fdNum = fd.getInt$();
+        if (fdNum == -1) return;
+        String cmd = "u " + fdNum;
+        internalModuleCtrl(cmd);
+    }
+
+    public static class SocketTags {
+        public int statsTag = -1;
+        public int statsUid = -1;
+    }
+
+    /**
+     * Sends commands to the kernel netfilter module.
+     *
+     * @param cmd command string for the qtaguid netfilter module. May not be null.
+     *   <p>Supports:
+     *     <ul><li>tag a socket:<br>
+     *        <code>t <i>sock_fd</i> <i>acct_tag</i> [<i>uid_in_case_caller_is_acting_on_behalf_of</i>]</code><br>
+     *     <code>*_tag</code> defaults to default_policy_tag_from_uid(uid_of_caller)<br>
+     *     <code>acct_tag</code> is either 0 or greater that 2^32.<br>
+     *     <code>uid_*</code> is only settable by privileged UIDs (DownloadManager,...)
+     *     </li>
+     *     <li>untag a socket, preserving counters:<br>
+     *       <code>u <i>sock_fd</i></code>
+     *     </li></ul>
+     *   <p>Notes:<br>
+     *   <ul><li><i>sock_fd</i> is withing the callers process space.</li>
+     *   <li><i>*_tag</i> are 64bit values</li></ul>
+     *
+     */
+    private void internalModuleCtrl(String cmd) throws IOException {
+        final FileOutputStream procOut;
+        // TODO: Use something like
+        //  android.os.SystemProperties.getInt("persist.bandwidth.enable", 0)
+        // to see if tagging should happen or not.
+        try {
+            procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl");
+        } catch (FileNotFoundException e) {
+            if (LOGI) {
+                System.logI("Can't talk to kernel module:" + e);
+            }
+            return;
+        }
+        try {
+            procOut.write(cmd.getBytes(Charsets.US_ASCII));
+        } finally {
+            procOut.close();
+        }
+    }
+
+    /**
+     * Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned
+     * base-10 format like {@code 2147483647}. Currently strips signed bit to
+     * avoid using {@link java.math.BigInteger}.
+     */
+    public static String tagToKernel(int tag) {
+        // TODO: eventually write in hex, since that's what proc exports
+        // TODO: migrate to direct integer instead of odd shifting
+        return Long.toString((((long) tag) << 32) & 0x7FFFFFFF00000000L);
+    }
+
+    /**
+     * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
+     * format like {@code 0x7fffffff00000000}.
+     */
+    public static int kernelToTag(String string) {
+        // TODO: migrate to direct integer instead of odd shifting
+        return (int) (Long.decode(string) >> 32);
+    }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 7b0882f..63fa504 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -75,7 +75,6 @@
 	android_nio_utils.cpp \
 	android_nfc_NdefMessage.cpp \
 	android_nfc_NdefRecord.cpp \
-	android_pim_EventRecurrence.cpp \
 	android_text_format_Time.cpp \
 	android_util_AssetManager.cpp \
 	android_util_Binder.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 21b0a42c..a61217a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,7 +131,6 @@
 extern int register_android_nio_utils(JNIEnv* env);
 extern int register_android_nfc_NdefMessage(JNIEnv *env);
 extern int register_android_nfc_NdefRecord(JNIEnv *env);
-extern int register_android_pim_EventRecurrence(JNIEnv* env);
 extern int register_android_text_format_Time(JNIEnv* env);
 extern int register_android_os_Debug(JNIEnv* env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
@@ -1103,7 +1102,6 @@
     REG_JNI(register_android_util_Log),
     REG_JNI(register_android_util_FloatMath),
     REG_JNI(register_android_text_format_Time),
-    REG_JNI(register_android_pim_EventRecurrence),
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 1b22e2d..18bd754 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -273,7 +273,8 @@
 // These must match the int values in Bitmap.java

 enum JavaEncodeFormat {

     kJPEG_JavaEncodeFormat = 0,

-    kPNG_JavaEncodeFormat = 1

+    kPNG_JavaEncodeFormat = 1,

+    kWEBP_JavaEncodeFormat = 2

 };

 

 static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,

@@ -288,6 +289,9 @@
     case kPNG_JavaEncodeFormat:

         fm = SkImageEncoder::kPNG_Type;

         break;

+    case kWEBP_JavaEncodeFormat:

+        fm = SkImageEncoder::kWEBP_Type;

+        break;

     default:

         return false;

     }

diff --git a/core/jni/android/graphics/ParcelSurfaceTexture.cpp b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
index 40966e1..754485f 100644
--- a/core/jni/android/graphics/ParcelSurfaceTexture.cpp
+++ b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
@@ -17,9 +17,11 @@
 #define LOG_TAG "ParcelSurfaceTexture"
 
 #include <gui/SurfaceTextureClient.h>
+#include <surfaceflinger/Surface.h>
 
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <android_runtime/android_view_Surface.h>
 
 #include <utils/Log.h>
 
@@ -96,7 +98,16 @@
     }
 }
 
-static void ParcelSurfaceTexture_init(JNIEnv* env, jobject thiz, jobject jSurfaceTexture)
+static void ParcelSurfaceTexture_initFromSurface(
+        JNIEnv* env, jobject thiz, jobject jSurface)
+{
+    sp<Surface> surface(Surface_getSurface(env, jSurface));
+    sp<ISurfaceTexture> iSurfaceTexture(surface->getSurfaceTexture());
+    ParcelSurfaceTexture_setISurfaceTexture(env, thiz, iSurfaceTexture);
+}
+
+static void ParcelSurfaceTexture_initFromSurfaceTexture(
+        JNIEnv* env, jobject thiz, jobject jSurfaceTexture)
 {
     sp<ISurfaceTexture> iSurfaceTexture(
             SurfaceTexture_getSurfaceTexture(env, jSurfaceTexture));
@@ -131,8 +142,10 @@
 
 static JNINativeMethod gParcelSurfaceTextureMethods[] = {
     {"nativeClassInit", "()V",   (void*)ParcelSurfaceTexture_classInit },
-    {"nativeInit", "(Landroid/graphics/SurfaceTexture;)V",
-      (void *)ParcelSurfaceTexture_init },
+    {"nativeInitFromSurface", "(Landroid/view/Surface;)V",
+      (void *)ParcelSurfaceTexture_initFromSurface },
+    {"nativeInitFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V",
+      (void *)ParcelSurfaceTexture_initFromSurfaceTexture },
     { "nativeFinalize", "()V", (void *)ParcelSurfaceTexture_finalize },
     { "nativeWriteToParcel", "(Landroid/os/Parcel;I)V",
       (void *)ParcelSurfaceTexture_writeToParcel },
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 0d28cb1..2de0932 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -91,7 +91,8 @@
     virtual void onFrameAvailable();
 
 private:
-    static JNIEnv* getJNIEnv();
+    static JNIEnv* getJNIEnv(bool* needsDetach);
+    static void detachJNI();
 
     jobject mWeakThiz;
     jclass mClazz;
@@ -103,37 +104,57 @@
     mClazz((jclass)env->NewGlobalRef(clazz))
 {}
 
-JNIEnv* JNISurfaceTextureContext::getJNIEnv() {
-    JNIEnv* env;
-    JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
-    JavaVM* vm = AndroidRuntime::getJavaVM();
-    int result = vm->AttachCurrentThread(&env, (void*) &args);
-    if (result != JNI_OK) {
-        LOGE("thread attach failed: %#x", result);
-        return NULL;
+JNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) {
+    *needsDetach = false;
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+        JavaVM* vm = AndroidRuntime::getJavaVM();
+        int result = vm->AttachCurrentThread(&env, (void*) &args);
+        if (result != JNI_OK) {
+            LOGE("thread attach failed: %#x", result);
+            return NULL;
+        }
+        *needsDetach = true;
     }
     return env;
 }
 
+void JNISurfaceTextureContext::detachJNI() {
+    JavaVM* vm = AndroidRuntime::getJavaVM();
+    int result = vm->DetachCurrentThread();
+    if (result != JNI_OK) {
+        LOGE("thread detach failed: %#x", result);
+    }
+}
+
 JNISurfaceTextureContext::~JNISurfaceTextureContext()
 {
-    JNIEnv* env = getJNIEnv();
+    bool needsDetach = false;
+    JNIEnv* env = getJNIEnv(&needsDetach);
     if (env != NULL) {
         env->DeleteGlobalRef(mWeakThiz);
         env->DeleteGlobalRef(mClazz);
     } else {
         LOGW("leaking JNI object references");
     }
+    if (needsDetach) {
+        detachJNI();
+    }
 }
 
 void JNISurfaceTextureContext::onFrameAvailable()
 {
-    JNIEnv *env = getJNIEnv();
+    bool needsDetach = false;
+    JNIEnv* env = getJNIEnv(&needsDetach);
     if (env != NULL) {
         env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
     } else {
         LOGW("onFrameAvailable event will not posted");
     }
+    if (needsDetach) {
+        detachJNI();
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -155,9 +176,9 @@
 }
 
 static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName,
-        jobject weakThiz)
+        jobject weakThiz, jboolean allowSynchronous)
 {
-    sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
+    sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName, allowSynchronous));
     if (surfaceTexture == 0) {
         jniThrowException(env, OutOfResourcesException,
                 "Unable to create native SurfaceTexture");
@@ -216,12 +237,12 @@
 
 static JNINativeMethod gSurfaceTextureMethods[] = {
     {"nativeClassInit",          "()V",   (void*)SurfaceTexture_classInit },
-    {"nativeInit",               "(ILjava/lang/Object;)V", (void*)SurfaceTexture_init },
+    {"nativeInit",               "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
     {"nativeFinalize",           "()V",   (void*)SurfaceTexture_finalize },
     {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
     {"nativeUpdateTexImage",     "()V",   (void*)SurfaceTexture_updateTexImage },
     {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
-    {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp }
+    {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp },
 };
 
 int register_android_graphics_SurfaceTexture(JNIEnv* env)
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index a5b2006..6a13876 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -461,12 +461,30 @@
                         Vector<GlyphRun> glyphRuns;
                         jchar* runGlyphs;
                         size_t runGlyphsCount = 0;
-                        size_t runIndex = 0;
+                        int32_t end = start + count;
                         for (size_t i = 0; i < rc; ++i) {
                             int32_t startRun;
                             int32_t lengthRun;
                             UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun);
 
+                            if (startRun >= end) {
+                              break;
+                            }
+
+                            int32_t endRun = startRun + lengthRun;
+                            if (endRun <= start) {
+                              continue;
+                            }
+
+                            if (startRun < start) {
+                              startRun = start;
+                            }
+                            if (endRun > end) {
+                              endRun = end;
+                            }
+
+                            lengthRun = endRun - startRun;
+
                             int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR;
                             jfloat runTotalAdvance = 0;
 #if DEBUG_GLYPHS
@@ -475,11 +493,10 @@
 #endif
                             computeRunValuesWithHarfbuzz(paint, chars, startRun,
                                     lengthRun, contextCount, newFlags,
-                                    outAdvances + runIndex, &runTotalAdvance,
+                                    outAdvances, &runTotalAdvance,
                                     &runGlyphs, &runGlyphsCount);
 
-                            runIndex += lengthRun;
-
+                            outAdvances += lengthRun;
                             *outTotalAdvance += runTotalAdvance;
                             *outGlyphsCount += runGlyphsCount;
 #if DEBUG_GLYPHS
diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp
index 6ae3e35..5c6f5e8 100644
--- a/core/jni/android_bluetooth_common.cpp
+++ b/core/jni/android_bluetooth_common.cpp
@@ -81,6 +81,16 @@
     {"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;
@@ -315,6 +325,22 @@
     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;
@@ -486,6 +512,55 @@
     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;
@@ -737,6 +812,21 @@
                           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;
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
index 3364703..2f5fd5a 100644
--- a/core/jni/android_bluetooth_common.h
+++ b/core/jni/android_bluetooth_common.h
@@ -149,6 +149,7 @@
 
 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);
@@ -164,8 +165,13 @@
 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);
diff --git a/core/jni/android_pim_EventRecurrence.cpp b/core/jni/android_pim_EventRecurrence.cpp
deleted file mode 100644
index 3e11569..0000000
--- a/core/jni/android_pim_EventRecurrence.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/* //device/libs/android_runtime/android_pim_EventRecurrence.cpp

-**

-** 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.

-*/

-

-#include <pim/EventRecurrence.h>

-#include "jni.h"

-#include "nativehelper/JNIHelp.h"

-#include <utils/String8.h>

-

-namespace android {

-

-struct cached_array_fields_t

-{

-    jfieldID array;

-    jfieldID count;

-};

-

-static jfieldID freq_field;

-static jfieldID until_field;

-static jfieldID count_field;

-static jfieldID interval_field;

-static jfieldID wkst_field;

-static cached_array_fields_t bysecond_fields;

-static cached_array_fields_t byminute_fields;

-static cached_array_fields_t byhour_fields;

-static cached_array_fields_t byday_fields;

-static cached_array_fields_t bydayNum_fields;

-static cached_array_fields_t bymonthday_fields;

-static cached_array_fields_t byyearday_fields;

-static cached_array_fields_t byweekno_fields;

-static cached_array_fields_t bymonth_fields;

-static cached_array_fields_t bysetpos_fields;

-

-static status_t

-set_array(JNIEnv* env, int inCount, int* inArray,

-            jobject This, const cached_array_fields_t& fields)

-{

-    if (inCount > 0) {

-        jintArray array = (jintArray) env->GetObjectField(This, fields.array);

-        if (array == NULL || env->GetArrayLength(array) < inCount) {

-            // +4 because it's cheap to allocate a little extra here, and

-            // that reduces the chance that we'll come back here again

-            array = env->NewIntArray(inCount+4);

-            env->SetObjectField(This, fields.array, array);

-        }

-        if (array == NULL) {

-            return NO_MEMORY;

-        }

-        env->SetIntArrayRegion(array, 0, inCount, inArray);

-

-    }

-    env->SetIntField(This, fields.count, inCount);

-    return NO_ERROR;

-}

-

-/*

- * In class android.pim.EventRecurrence

- *  public native int parse(String str);

- */

-#define SET_ARRAY_AND_CHECK(name) \

-    /*printf("setting " #name " to %d elements\n", er.name##Count);*/ \

-    if (set_array(env, er.name##Count, er.name, This, name##_fields) \

-            != NO_ERROR) { \

-        jniThrowException(env, "java/lang/RuntimeException", \

-                "EventRecurrence.parse error setting field " #name " or " \

-                #name "Count."); \

-        return ; \

-    }

-static void

-EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)

-{

-    if (jstr == NULL) {

-        jniThrowNullPointerException(env, "EventRecurrence.parse str parameter null");

-        return ;

-    }

-    const jchar* jchars = env->GetStringChars(jstr, NULL);

-    jsize len = env->GetStringLength(jstr);

-    String16 str(jchars, len);

-    env->ReleaseStringChars(jstr, jchars);

-

-    //printf("the string was '%s'\n", String8(str).string());

-

-    EventRecurrence er;

-    if (NO_ERROR != er.parse(str)) {

-        String8 msg("Error parsing recurrence: '");

-        msg.append(String8(str));

-        msg.append("'");

-

-        jniThrowException(env,

-                "android/pim/EventRecurrence$InvalidFormatException",

-                msg.string());

-        return ;

-    }

-

-    jstring untilStr;

-    if (er.until.size() > 0) {

-        untilStr = env->NewString(er.until.string(), er.until.size());

-        if (untilStr == NULL) {

-            jniThrowException(env, "java/lang/RuntimeException",

-                    "EventRecurrence.parse error setting field 'until'");

-            return ;

-        }

-    } else {

-        untilStr = NULL;

-    }

-    env->SetObjectField(This, until_field, untilStr);

-

-    env->SetIntField(This, freq_field, er.freq);

-    env->SetIntField(This, count_field, er.count);

-    env->SetIntField(This, interval_field, er.interval);

-    env->SetIntField(This, wkst_field, er.wkst);

-

-    SET_ARRAY_AND_CHECK(bysecond)

-    SET_ARRAY_AND_CHECK(byminute)

-    SET_ARRAY_AND_CHECK(byhour)

-    SET_ARRAY_AND_CHECK(byday)

-    // we'll just set the bydayCount field twice, it'll be less code total

-    if (set_array(env, er.bydayCount, er.bydayNum, This, bydayNum_fields)

-            != NO_ERROR) {

-        jniThrowException(env, "java/lang/RuntimeException",

-                "EventRecurrence.parse error setting field bydayNum or "

-                "bydayCount.");

-        return ;

-    }

-    SET_ARRAY_AND_CHECK(bymonthday)

-    SET_ARRAY_AND_CHECK(byyearday)

-    SET_ARRAY_AND_CHECK(byweekno)

-    SET_ARRAY_AND_CHECK(bymonth)

-    SET_ARRAY_AND_CHECK(bysetpos)

-}

-

-/*

- * JNI registration.

- */

-static JNINativeMethod METHODS[] = {

-    /* name, signature, funcPtr */

-    { "parseNative", "(Ljava/lang/String;)V", (void*)EventRecurrence_parse }

-};

-

-static const char*const CLASS_NAME = "android/pim/EventRecurrence";

-

-int register_android_pim_EventRecurrence(JNIEnv* env)

-{

-    jclass clazz = env->FindClass(CLASS_NAME);

-    if (clazz == NULL) {

-        LOGE("Field lookup unable to find class '%s'\n", CLASS_NAME);

-        return -1;

-    }

-

-    freq_field = env->GetFieldID(clazz, "freq", "I");

-    count_field = env->GetFieldID(clazz, "count", "I");

-    interval_field = env->GetFieldID(clazz, "interval", "I");

-    wkst_field = env->GetFieldID(clazz, "wkst", "I");

-

-    until_field = env->GetFieldID(clazz, "until", "Ljava/lang/String;");

-

-    bysecond_fields.array = env->GetFieldID(clazz, "bysecond", "[I");

-    bysecond_fields.count = env->GetFieldID(clazz, "bysecondCount", "I");

-    byminute_fields.array = env->GetFieldID(clazz, "byminute", "[I");

-    byminute_fields.count = env->GetFieldID(clazz, "byminuteCount", "I");

-    byhour_fields.array = env->GetFieldID(clazz, "byhour", "[I");

-    byhour_fields.count = env->GetFieldID(clazz, "byhourCount", "I");

-    byday_fields.array = env->GetFieldID(clazz, "byday", "[I");

-    byday_fields.count = env->GetFieldID(clazz, "bydayCount", "I");

-    bydayNum_fields.array = env->GetFieldID(clazz, "bydayNum", "[I");

-    bydayNum_fields.count = byday_fields.count;

-    bymonthday_fields.array = env->GetFieldID(clazz, "bymonthday", "[I");

-    bymonthday_fields.count = env->GetFieldID(clazz, "bymonthdayCount", "I");

-    byyearday_fields.array = env->GetFieldID(clazz, "byyearday", "[I");

-    byyearday_fields.count = env->GetFieldID(clazz, "byyeardayCount", "I");

-    byweekno_fields.array = env->GetFieldID(clazz, "byweekno", "[I");

-    byweekno_fields.count = env->GetFieldID(clazz, "byweeknoCount", "I");

-    bymonth_fields.array = env->GetFieldID(clazz, "bymonth", "[I");

-    bymonth_fields.count = env->GetFieldID(clazz, "bymonthCount", "I");

-    bysetpos_fields.array = env->GetFieldID(clazz, "bysetpos", "[I");

-    bysetpos_fields.count = env->GetFieldID(clazz, "bysetposCount", "I");

-

-    return jniRegisterNativeMethods(env, CLASS_NAME,

-        METHODS, sizeof(METHODS)/sizeof(METHODS[0]));

-}

-

-}; // namespace android

diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 59b97c2..fb25486 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -72,6 +72,8 @@
 static jmethodID method_onInputDeviceConnectionResult;
 static jmethodID method_onPanDevicePropertyChanged;
 static jmethodID method_onPanDeviceConnectionResult;
+static jmethodID method_onHealthDevicePropertyChanged;
+static jmethodID method_onHealthDeviceChannelChanged;
 
 typedef event_loop_native_data_t native_data_t;
 
@@ -139,6 +141,10 @@
                                                "(Ljava/lang/String;[Ljava/lang/String;)V");
     method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
                                                "(Ljava/lang/String;I)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");
 
@@ -271,6 +277,15 @@
             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);
@@ -459,6 +474,12 @@
             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)) {
@@ -985,6 +1006,58 @@
            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.NetworkServer",
+                                     "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);
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index ac75634..036c34c 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -19,12 +19,16 @@
 #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"
@@ -1255,6 +1259,400 @@
     return JNI_FALSE;
 }
 
+static jstring registerHealthApplicationNative(JNIEnv *env, jobject object,
+                                           jint dataType, jstring role,
+                                           jstring name, jstring channelType) {
+    LOGV("%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) {
+            LOGE("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) {
+    LOGV("%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) {
+            LOGE("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 {
+            LOGE("--_Call made getting the patch...");
+            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);
+                LOGE("----Path is %s", c_path);
+            }
+            dbus_message_unref(reply);
+        }
+    }
+#endif
+    return path;
+}
+
+static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object,
+                                                    jstring path) {
+    LOGV("%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) {
+    LOGV("%s", __FUNCTION__);
+    jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+    native_data_t *nat = get_native_data(env, object);
+
+    if (nat) {
+        DBusError err;
+        dbus_error_init(&err);
+
+        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);
+        LOGE("Params...%s, %s, %s \n", c_device_path, c_app_path, c_config);
+
+        DBusMessage *reply  = dbus_func_args(env, nat->conn,
+                                             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);
+
+        if (!reply) {
+            if (dbus_error_is_set(&err)) {
+                LOG_AND_FREE_DBUS_ERROR(&err);
+            }
+        } else {
+            result = JNI_TRUE;
+        }
+    }
+#endif
+    return result;
+}
+
+static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath,
+                                     jstring channelPath) {
+    LOGE("%s", __FUNCTION__);
+    jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+    native_data_t *nat = get_native_data(env, object);
+
+    if (nat) {
+        DBusError err;
+        dbus_error_init(&err);
+
+        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
+        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
+
+        DBusMessage *reply = dbus_func_args(env, nat->conn,
+                                            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);
+
+        if (!reply) {
+            if (dbus_error_is_set(&err)) {
+                LOG_AND_FREE_DBUS_ERROR(&err);
+            }
+        } else {
+            result = JNI_TRUE;
+        }
+    }
+#endif
+    return result;
+}
+
+static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) {
+    LOGE("%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);
+
+        LOGE("---Args %s", c_device_path);
+        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) {
+    LOGE("%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);
+
+        LOGE("---Args %s", c_channel_path);
+
+        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);
+                    LOGE("----Path is %s", env->GetStringUTFChars(path, NULL));
+                    env->ReleaseStringUTFChars(name, c_name);
+                    return path;
+                }
+                env->ReleaseStringUTFChars(name, c_name);
+            }
+        }
+    }
+#endif
+    return NULL;
+}
+
+static jboolean releaseChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
+    LOGV("%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) {
+    LOGV("%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;
+
+        LOGE("---got fd %d\n", fd);
+        // Create FileDescriptor object
+        jobject fileDesc = jniCreateFileDescriptor(env, fd);
+        if (fileDesc == NULL) {
+            // FileDescriptor constructor has thrown an exception
+            releaseChannelFdNative(env, object, channelPath);
+            LOGE("---File Desc is null");
+            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);
+            LOGE("---Parcel File Desc is null");
+            return NULL;
+        }
+
+        return parcelFileDesc;
+    }
+#endif
+    return NULL;
+}
+
+
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"classInitNative", "()V", (void*)classInitNative},
@@ -1317,6 +1715,24 @@
     {"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;)Z",
+              (void *)createChannelNative},
+    {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;)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},
 };
 
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index e301e44..537aae6 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -608,8 +608,8 @@
 }
 
 static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
-        jintArray layerInfo) {
-    Layer* layer = LayerRenderer::createTextureLayer();
+        jboolean isOpaque, jintArray layerInfo) {
+    Layer* layer = LayerRenderer::createTextureLayer(isOpaque);
 
     if (layer) {
         jint* storage = env->GetIntArrayElements(layerInfo, NULL);
@@ -645,7 +645,7 @@
 }
 
 static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
-        Layer* layer, jint width, jint height, jobject surface) {
+        Layer* layer, jint width, jint height, jboolean isOpaque, jobject surface) {
     float transform[16];
     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
 
@@ -653,7 +653,7 @@
     surfaceTexture->getTransformMatrix(transform);
     GLenum renderTarget = surfaceTexture->getCurrentTextureTarget();
 
-    LayerRenderer::updateTextureLayer(layer, width, height, renderTarget, transform);
+    LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
 }
 
 static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
@@ -795,8 +795,8 @@
     { "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 },
-    { "nCreateTextureLayer",     "([I)I",      (void*) android_view_GLES20Canvas_createTextureLayer },
-    { "nUpdateTextureLayer",     "(IIILandroid/graphics/SurfaceTexture;)V",
+    { "nCreateTextureLayer",     "(Z[I)I",     (void*) android_view_GLES20Canvas_createTextureLayer },
+    { "nUpdateTextureLayer",     "(IIIZLandroid/graphics/SurfaceTexture;)V",
                                                (void*) android_view_GLES20Canvas_updateTextureLayer },
     { "nDestroyLayer",           "(I)V",       (void*) android_view_GLES20Canvas_destroyLayer },
     { "nDestroyLayerDeferred",   "(I)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 70c2f7b..0dc9293 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -156,7 +156,7 @@
 
 static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
 {
-    sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
+    sp<Surface> result(Surface_getSurface(env, clazz));
     if (result == 0) {
         /*
          * if this method is called from the WindowManager's process, it means
@@ -189,6 +189,11 @@
     return env->IsInstanceOf(obj, surfaceClass);
 }
 
+sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) {
+    sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface));
+    return surface;
+}
+
 static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
 {
     Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
deleted file mode 100644
index 1f7aeee..0000000
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
index 94d27cf..9409890 100644
--- a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
+++ b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
index 94d27cf..55acc9a 100644
--- a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
+++ b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
deleted file mode 100755
index 4c1d89d..0000000
--- a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png
deleted file mode 100644
index 6963a0e..0000000
--- a/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_holo_dark.9.png
deleted file mode 100755
index 64e2052..0000000
--- a/core/res/res/drawable-hdpi/cab_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
deleted file mode 100644
index 3a84de9..0000000
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
index e21a87c..0f4bfe6 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
index 3283f99..995705d 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_16.png b/core/res/res/drawable-hdpi/spinner_black_16.png
index eb34867..ef5ca35 100644
--- a/core/res/res/drawable-hdpi/spinner_black_16.png
+++ b/core/res/res/drawable-hdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_20.png b/core/res/res/drawable-hdpi/spinner_black_20.png
index dac06d7..d938931 100644
--- a/core/res/res/drawable-hdpi/spinner_black_20.png
+++ b/core/res/res/drawable-hdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_48.png b/core/res/res/drawable-hdpi/spinner_black_48.png
index 337f72a..9d1efb7 100644
--- a/core/res/res/drawable-hdpi/spinner_black_48.png
+++ b/core/res/res/drawable-hdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_76.png b/core/res/res/drawable-hdpi/spinner_black_76.png
index 2edc3e7..0d90881 100644
--- a/core/res/res/drawable-hdpi/spinner_black_76.png
+++ b/core/res/res/drawable-hdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_16.png b/core/res/res/drawable-hdpi/spinner_white_16.png
index 7914a68..32fa447 100644
--- a/core/res/res/drawable-hdpi/spinner_white_16.png
+++ b/core/res/res/drawable-hdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_48.png b/core/res/res/drawable-hdpi/spinner_white_48.png
index faee8ca..31fa267 100644
--- a/core/res/res/drawable-hdpi/spinner_white_48.png
+++ b/core/res/res/drawable-hdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_76.png b/core/res/res/drawable-hdpi/spinner_white_76.png
index cd26379..9f63292 100644
--- a/core/res/res/drawable-hdpi/spinner_white_76.png
+++ b/core/res/res/drawable-hdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/title_bar_shadow.9.png b/core/res/res/drawable-hdpi/title_bar_shadow.9.png
new file mode 100644
index 0000000..e6dab63
--- /dev/null
+++ b/core/res/res/drawable-hdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_code_lock_default.png b/core/res/res/drawable-large-mdpi/btn_code_lock_default_holo.png
similarity index 100%
rename from core/res/res/drawable-xlarge-mdpi/btn_code_lock_default.png
rename to core/res/res/drawable-large-mdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_code_lock_default.png b/core/res/res/drawable-large-mdpi/btn_code_lock_touched_holo.png
similarity index 100%
copy from core/res/res/drawable-xlarge-mdpi/btn_code_lock_default.png
copy to core/res/res/drawable-large-mdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png
similarity index 100%
rename from core/res/res/drawable-xlarge-mdpi/indicator_code_lock_drag_direction_green_up.png
rename to core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/indicator_code_lock_drag_direction_red_up.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_red_up.png
similarity index 100%
rename from core/res/res/drawable-xlarge-mdpi/indicator_code_lock_drag_direction_red_up.png
rename to core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_red_up.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/indicator_code_lock_point_area_default.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_default_holo.png
similarity index 100%
rename from core/res/res/drawable-xlarge-mdpi/indicator_code_lock_point_area_default.png
rename to core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_green_holo.png
similarity index 100%
rename from core/res/res/drawable-xlarge-mdpi/indicator_code_lock_point_area_green.png
rename to core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/indicator_code_lock_point_area_red.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_red_holo.png
similarity index 100%
rename from core/res/res/drawable-xlarge-mdpi/indicator_code_lock_point_area_red.png
rename to core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
deleted file mode 100644
index 48cc017..0000000
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
index 7d11275..82fc3b2 100644
--- a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
index 7d11275..d1fe1ad 100644
--- a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
deleted file mode 100755
index 66cbe48..0000000
--- a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png
deleted file mode 100644
index b6508fc..0000000
--- a/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_holo_dark.9.png
deleted file mode 100755
index 7daae1f..0000000
--- a/core/res/res/drawable-mdpi/cab_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
deleted file mode 100644
index cb3d0f2..0000000
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
index c10344f..754d7bc 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
index 08c6cfe..0187a02 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_16.png b/core/res/res/drawable-mdpi/spinner_black_16.png
index 5ee33ce..4b7fdfe 100644
--- a/core/res/res/drawable-mdpi/spinner_black_16.png
+++ b/core/res/res/drawable-mdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_20.png b/core/res/res/drawable-mdpi/spinner_black_20.png
index e55b60d..86d7a20 100755
--- a/core/res/res/drawable-mdpi/spinner_black_20.png
+++ b/core/res/res/drawable-mdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_48.png b/core/res/res/drawable-mdpi/spinner_black_48.png
index 3a68192..f1571f9 100644
--- a/core/res/res/drawable-mdpi/spinner_black_48.png
+++ b/core/res/res/drawable-mdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_76.png b/core/res/res/drawable-mdpi/spinner_black_76.png
index ec57460..e9f6e8f 100644
--- a/core/res/res/drawable-mdpi/spinner_black_76.png
+++ b/core/res/res/drawable-mdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_16.png b/core/res/res/drawable-mdpi/spinner_white_16.png
index dd2e1fd..650e315 100644
--- a/core/res/res/drawable-mdpi/spinner_white_16.png
+++ b/core/res/res/drawable-mdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_48.png b/core/res/res/drawable-mdpi/spinner_white_48.png
index d25a33e..11eacf8 100644
--- a/core/res/res/drawable-mdpi/spinner_white_48.png
+++ b/core/res/res/drawable-mdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_76.png b/core/res/res/drawable-mdpi/spinner_white_76.png
index f53e8ff..6c31bc3 100644
--- a/core/res/res/drawable-mdpi/spinner_white_76.png
+++ b/core/res/res/drawable-mdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_shadow.9.png b/core/res/res/drawable-mdpi/title_bar_shadow.9.png
new file mode 100644
index 0000000..dbcefee
--- /dev/null
+++ b/core/res/res/drawable-mdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
new file mode 100644
index 0000000..f607251
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
new file mode 100644
index 0000000..e057cdd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
new file mode 100644
index 0000000..544924e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
new file mode 100644
index 0000000..2d28009
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_code_lock_touched.png b/core/res/res/drawable-xlarge-mdpi/btn_code_lock_touched.png
deleted file mode 100644
index 45cc20d..0000000
--- a/core/res/res/drawable-xlarge-mdpi/btn_code_lock_touched.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_default.png b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_default.png
new file mode 100644
index 0000000..9f7a132
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_default.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_touched.png b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_touched.png
new file mode 100644
index 0000000..9f7a132
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/layout-land/ssl_certificate.xml b/core/res/res/layout-land/ssl_certificate.xml
new file mode 100644
index 0000000..56e4e70
--- /dev/null
+++ b/core/res/res/layout-land/ssl_certificate.xml
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical" >
+
+        <!-- Placeholder for the success message or one or more warnings -->
+        <LinearLayout
+            android:id="@+id/placeholder"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginTop="12dip"
+            android:orientation="vertical" />
+
+        <!-- Dialog-title line separator -->
+        <ImageView
+            android:id="@+id/title_separator"
+            android:src="@android:drawable/divider_horizontal_dark"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scaleType="fitXY"
+            android:layout_weight="1"
+            android:gravity="fill_horizontal"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="12dip" />
+
+        <TableLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:shrinkColumns="1"
+            android:orientation="vertical">
+
+            <!-- Issued to: -->
+            <TextView
+                android:id="@+id/issued_to_header"
+                android:text="@string/issued_to"
+                android:textStyle="bold"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- Common name: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/to_common_header"
+                    android:text="@string/common_name"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/to_common"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organization: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/to_org_header"
+                    android:text="@string/org_name"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/to_org"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organizational unit: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/to_org_unit_header"
+                    android:text="@string/org_unit"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/to_org_unit"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="12dip" />
+            </TableRow>
+
+            <!-- Issued by: -->
+            <TextView
+                android:id="@+id/issued_to_header"
+                android:text="@string/issued_by"
+                android:textStyle="bold"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- Common name: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/by_common_header"
+                    android:text="@string/common_name"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/by_common"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organization: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/by_org_header"
+                    android:text="@string/org_name"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/by_org"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organizational unit: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/by_org_unit_header"
+                    android:text="@string/org_unit"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/by_org_unit"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="12dip" />
+            </TableRow>
+
+            <!-- Validity Dates: -->
+            <TextView
+                android:id="@+id/validity_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/validity_period"
+                android:textStyle="bold"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- Issued On: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/issued_on_header"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/issued_on"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/issued_on"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+
+            </TableRow>
+
+            <!-- Expires On: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/expires_on_header"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/expires_on"
+                    android:gravity="left"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/expires_on"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:gravity="left"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="12dip" />
+            </TableRow>
+
+        </TableLayout>
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/layout-large/action_bar_home.xml b/core/res/res/layout-large/action_bar_home.xml
deleted file mode 100644
index 86580bc..0000000
--- a/core/res/res/layout-large/action_bar_home.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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.
--->
-
-<view xmlns:android="http://schemas.android.com/apk/res/android"
-      class="com.android.internal.widget.ActionBarView$HomeView"
-      android:layout_width="wrap_content"
-      android:layout_height="match_parent"
-      android:background="?android:attr/selectableItemBackground" >
-    <ImageView android:id="@android:id/up"
-               android:src="?android:attr/homeAsUpIndicator"
-               android:layout_gravity="center_vertical|left"
-               android:visibility="gone"
-               android:layout_width="wrap_content"
-               android:layout_height="wrap_content"
-               android:layout_marginRight="-12dip" />
-    <ImageView android:id="@android:id/home"
-               android:layout_width="wrap_content"
-               android:layout_height="wrap_content"
-               android:paddingLeft="16dip"
-               android:paddingRight="16dip"
-               android:paddingTop="4dip"
-               android:paddingBottom="4dip"
-               android:adjustViewBounds="true"
-               android:layout_gravity="center"
-               android:scaleType="fitCenter" />
-</view>
diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml
new file mode 100644
index 0000000..004d52a
--- /dev/null
+++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/datePicker"
+    android:layout_gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="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 9779074..56c832c 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
@@ -26,7 +26,7 @@
         android:layout_width="match_parent"
         android:layout_height="0px"
         android:layout_weight="1"
-        android:layout_above="@+id/emergencyCall">
+        android:layout_above="@+id/emergencyCallButton">
         <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent">
@@ -123,7 +123,7 @@
 
     <!-- emergency call button at bottom center -->
     <Button
-        android:id="@+id/emergencyCall"
+        android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_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 1783088..6579e76 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -95,7 +95,7 @@
 
     <!-- emergency call button NOT CURRENTLY USED -->
     <Button
-        android:id="@+id/emergencyCall"
+        android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:drawableLeft="@drawable/ic_emergency"
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 63241dd..c63b0ff 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -87,7 +87,7 @@
 
         <!-- emergency call button -->
         <Button
-            android:id="@+id/emergencyCall"
+            android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:drawableLeft="@drawable/ic_emergency"
@@ -98,4 +98,4 @@
         />
 
     </LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
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 b8cbe51..c65dd83 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
@@ -104,7 +104,7 @@
             android:textSize="18sp"
             />
 
-        <Button android:id="@+id/emergencyCall"
+        <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
             android:layout_alignParentBottom="true"
             android:layout_centerHorizontal="true"
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 009148f..d8bea56 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
@@ -93,7 +93,7 @@
         android:layout_width="match_parent"
         android:layout_height="1dip"
         android:layout_marginTop="6dip"
-        android:layout_above="@id/emergencyCall"
+        android:layout_above="@id/emergencyCallButton"
         android:background="@android:drawable/divider_horizontal_dark"
     />
 
@@ -107,7 +107,7 @@
 
         <!-- emergency call button -->
         <Button
-            android:id="@+id/emergencyCall"
+            android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:drawableLeft="@android:drawable/ic_emergency"
diff --git a/core/res/res/layout-sw600dp/number_picker.xml b/core/res/res/layout-sw600dp/number_picker.xml
new file mode 100644
index 0000000..807daf2
--- /dev/null
+++ b/core/res/res/layout-sw600dp/number_picker.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <ImageButton android:id="@+id/increment"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/numberPickerUpButtonStyle"
+        android:contentDescription="@string/number_picker_increment_button" />
+
+    <EditText android:id="@+id/numberpicker_input"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/numberPickerInputTextStyle" />
+
+    <ImageButton android:id="@+id/decrement"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/numberPickerDownButtonStyle"
+        android:contentDescription="@string/number_picker_decrement_button" />
+
+</merge>
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index 7f7c55c..9612710 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -25,14 +25,13 @@
                android:visibility="gone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
-               android:layout_marginRight="-4dip" />
+               android:layout_marginRight="-8dip" />
     <ImageView android:id="@android:id/home"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
-               android:paddingLeft="8dip"
-               android:paddingRight="8dip"
-               android:paddingTop="@dimen/action_bar_icon_vertical_padding"
-               android:paddingBottom="@dimen/action_bar_icon_vertical_padding"
+               android:layout_marginRight="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"
                android:adjustViewBounds="true"
                android:scaleType="fitCenter" />
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index 4206dcb..a8f0c22 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -29,10 +29,10 @@
                  android:layout_height="wrap_content"
                  android:layout_gravity="center"
                  android:visibility="gone"
-                 android:paddingTop="@dimen/action_bar_icon_vertical_padding"
-                 android:paddingBottom="@dimen/action_bar_icon_vertical_padding"
-                 android:paddingLeft="4dip"
-                 android:paddingRight="4dip"
+                 android:layout_marginTop="4dip"
+                 android:layout_marginBottom="4dip"
+                 android:layout_marginLeft="4dip"
+                 android:layout_marginRight="4dip"
                  android:scaleType="fitCenter"
                  android:adjustViewBounds="true"
                  android:background="@null"
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 004d52a..db8f311 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -22,4 +22,6 @@
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:spinnersShown="true"
+    android:calendarViewShown="false"
     />
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index 026cbfb..8627637 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -77,7 +77,8 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="22dip"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/keyguard_screen_glogin_unlock.xml b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
index 8a46546..0e5fe78 100644
--- a/core/res/res/layout/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
@@ -26,7 +26,7 @@
         android:layout_width="match_parent"
         android:layout_height="0px"
         android:layout_weight="1"
-        android:layout_above="@+id/emergencyCall">
+        android:layout_above="@+id/emergencyCallButton">
         <RelativeLayout 
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -114,7 +114,7 @@
 
     <!-- emergency call button at bottom center -->
     <Button
-        android:id="@+id/emergencyCall"
+        android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_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 aac0853..8ba08f6 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 **
-** Copyright 2008, The Android Open Source Project
+** 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.
@@ -17,89 +17,180 @@
 */
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- This is the general lock screen which shows information about the
+  state of the device, as well as instructions on how to get past it
+  depending on the state of the device.-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:rowCount="11"
+    android:id="@+id/root"
+    android:clipChildren="false">
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-    />
+    <!-- Column 0 -->
+    <Space android:height="20dip"/>
 
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+    <com.android.internal.widget.DigitalClock android:id="@+id/time"
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="8dip"
+        android:layout_gravity="right">
 
-        <!-- left side: status -->
-        <include layout="@layout/keyguard_screen_status_land"
+       <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+        top of the other. Hence the redundant layout... -->
+        <TextView android:id="@+id/timeDisplayBackground"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_centerVertical="true"
-            android:layout_alignParentLeft="true"/>
-
-        <!-- right side: password -->
-        <LinearLayout
-            android:layout_width="300dip"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:layout_alignParentRight="true"
-            android:layout_centerVertical="true">
-
-            <!-- Password entry field -->
-            <EditText android:id="@+id/passwordEntry"
-                android:layout_height="wrap_content"
-                android:layout_width="match_parent"
-                android:singleLine="true"
-                android:textStyle="normal"
-                android:inputType="textPassword"
-                android:gravity="center"
-                android:textSize="24sp"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:background="@drawable/lockscreen_password_field_dark"
-                android:textColor="#ffffffff"
-                />
-
-            <!-- Numeric keyboard -->
-            <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
-                android:layout_width="300dip"
-                android:layout_height="400dip"
-                android:background="#40000000"
-                android:layout_marginTop="5dip"
-                android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
-                android:visibility="gone"
+            android:singleLine="true"
+            android:ellipsize="none"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:layout_marginBottom="6dip"
+            android:textColor="@color/lockscreen_clock_background"
             />
-        </LinearLayout>
 
-    </RelativeLayout>
+        <TextView android:id="@+id/timeDisplayForeground"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="none"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:layout_marginBottom="6dip"
+            android:textColor="@color/lockscreen_clock_foreground"
+            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignTop="@id/timeDisplayBackground"
+            />
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
+    </com.android.internal.widget.DigitalClock>
+
+    <TextView
+        android:id="@+id/date"
+        android:layout_below="@id/time"
+        android:layout_marginTop="6dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:layout_gravity="right"
+        />
+
+    <TextView
+        android:id="@+id/alarm_status"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawablePadding="4dip"
+        android:layout_marginTop="4dip"
+        android:layout_gravity="right"
+        />
+
+    <TextView
+        android:id="@+id/status1"
+        android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawablePadding="4dip"
+        android:layout_gravity="right"
+        />
+
+    <TextView
+        android:id="@+id/status2"
+        android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawablePadding="4dip"
+        android:layout_gravity="right"
+        />
+
+    <TextView
+        android:id="@+id/screenLocked"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:gravity="center"
+        android:layout_marginTop="4dip"
+        android:drawablePadding="4dip"
+        android:layout_gravity="right"
+        />
+
+    <Space android:height="20dip"/>
+
+    <TextView
+        android:id="@+id/carrier"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:layout_gravity="right"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:textColor="?android:attr/textColorSecondary"
     />
 
-    <!-- Alphanumeric keyboard -->
-    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="@drawable/password_keyboard_background_holo"
-        android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
-        android:keyTextSize="18dip"
-        android:visibility="gone"
+    <!-- "emergency calls only" shown when sim is missing or PUKd -->
+    <TextView
+        android:id="@+id/emergencyCallText"
+        android:layout_marginTop="20dip"
+        android:layout_gravity="right"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:text="@string/emergency_calls_only"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:textColor="?android:attr/textColorSecondary"
     />
 
-    <!-- emergency call button NOT CURRENTLY USED -->
     <Button
-        android:id="@+id/emergencyCall"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:drawableLeft="@drawable/ic_emergency"
-        android:drawablePadding="8dip"
+        android:id="@+id/emergencyCallButton"
+        android:layout_gravity="right"
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
         android:text="@string/lockscreen_emergency_call"
-        android:visibility="gone"
-        style="@style/Widget.Button.Transparent"
+        style="?android:attr/buttonBarButtonStyle"
+        android:drawablePadding="8dip"
+        android:visibility="visible"
     />
 
-</LinearLayout>
+    <!-- Column 1 -->
+    <Space android:layout_columnWeight="1" android:layout_rowSpan="11" />
+
+    <!-- Column 2 - password entry field and PIN keyboard -->
+    <LinearLayout
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:orientation="vertical"
+        android:layout_gravity="center|fill"
+        android:layout_rowSpan="11">
+
+        <EditText android:id="@+id/passwordEntry"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:singleLine="true"
+            android:textStyle="normal"
+            android:inputType="textPassword"
+            android:layout_gravity="center"
+            android:textSize="24sp"
+            android:minEms="8"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:background="@drawable/lockscreen_password_field_dark"
+            android:textColor="?android:attr/textColorPrimary"
+            />
+
+        <!-- Numeric keyboard -->
+        <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:layout_gravity="center"
+            android:background="#40000000"
+            android:layout_marginTop="5dip"
+            android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+            android:visibility="visible"
+        />
+
+    </LinearLayout>
+
+</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 7805672b..6953ac8 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -24,24 +24,27 @@
     <!-- top: status -->
     <RelativeLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+            android:layout_height="wrap_content"
+            android:layout_marginRight="16dip">
         <include layout="@layout/keyguard_screen_status_port"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+            android:layout_alignParentRight="true"/>
     </RelativeLayout>
 
     <!-- emergency call button -->
     <Button
-        android:id="@+id/emergencyCall"
+        android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:drawableLeft="@drawable/ic_emergency"
+        android:layout_marginTop="4dip"
+        android:layout_marginRight="16dip"
+        android:layout_gravity="right"
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
         android:drawablePadding="8dip"
         android:text="@string/lockscreen_emergency_call"
-        android:visibility="gone"
-        style="@style/Widget.Button.Transparent"
+        style="?android:attr/buttonBarButtonStyle"
     />
 
     <!-- bottom: password -->
@@ -55,6 +58,8 @@
         android:inputType="textPassword"
         android:gravity="center"
         android:textSize="22sp"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
         android:background="@drawable/lockscreen_password_field_dark"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textColor="#ffffffff"/>
@@ -83,4 +88,17 @@
         android:visibility="gone"
     />
 
-</LinearLayout>
\ No newline at end of file
+    <TextView
+        android:id="@+id/carrier"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginBottom="8dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawablePadding="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        />
+
+</LinearLayout>
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 244afbe..dff2a3f 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -102,7 +102,7 @@
             android:textSize="18sp"
             />
 
-        <Button android:id="@+id/emergencyCall"
+        <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
             android:layout_alignParentBottom="true"
             android:layout_centerHorizontal="true"
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 009148f..d8bea56 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
@@ -93,7 +93,7 @@
         android:layout_width="match_parent"
         android:layout_height="1dip"
         android:layout_marginTop="6dip"
-        android:layout_above="@id/emergencyCall"
+        android:layout_above="@id/emergencyCallButton"
         android:background="@android:drawable/divider_horizontal_dark"
     />
 
@@ -107,7 +107,7 @@
 
         <!-- emergency call button -->
         <Button
-            android:id="@+id/emergencyCall"
+            android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:drawableLeft="@android:drawable/ic_emergency"
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 d58fb23..11a6e12 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -164,7 +164,7 @@
             android:textSize="18sp"
             />
 
-        <Button android:id="@+id/emergencyCall"
+        <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
             android:layout_alignParentBottom="true"
             android:layout_centerHorizontal="true"
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 5e392ef..e5e0459 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
@@ -159,7 +159,7 @@
         android:layout_width="match_parent"
         android:layout_height="1dip"
         android:layout_marginTop="6dip"
-        android:layout_above="@id/emergencyCall"
+        android:layout_above="@id/emergencyCallButton"
         android:background="@android:drawable/divider_horizontal_dark"
     />
 
@@ -173,7 +173,7 @@
 
         <!-- emergency call button -->
         <Button
-            android:id="@+id/emergencyCall"
+            android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:drawableLeft="@android:drawable/ic_emergency"
diff --git a/core/res/res/layout/keyguard_screen_status_land.xml b/core/res/res/layout/keyguard_screen_status_land.xml
index 8a02e1f..021faa3 100644
--- a/core/res/res/layout/keyguard_screen_status_land.xml
+++ b/core/res/res/layout/keyguard_screen_status_land.xml
@@ -26,17 +26,6 @@
         android:gravity="left"
         >
 
-    <TextView
-        android:id="@+id/carrier"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
-        android:drawablePadding="4dip"
-        android:singleLine="true"
-        android:ellipsize="marquee"
-        />
-
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -52,7 +41,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="40sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_background"
             android:layout_marginBottom="6dip"
@@ -63,7 +52,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="40sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_foreground"
             android:layout_alignLeft="@id/timeDisplayBackground"
@@ -71,19 +60,6 @@
             android:layout_marginBottom="6dip"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="18sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <LinearLayout
@@ -97,16 +73,20 @@
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
 
         <TextView
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="30dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
 
     </LinearLayout>
 
@@ -116,8 +96,10 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_marginTop="10dip"
         android:drawablePadding="4dip"
         android:visibility="gone"
@@ -129,7 +111,9 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="10dip"
-        android:textSize="17sp"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_status_port.xml b/core/res/res/layout/keyguard_screen_status_port.xml
index 1e87fb3..f84e61c2 100644
--- a/core/res/res/layout/keyguard_screen_status_port.xml
+++ b/core/res/res/layout/keyguard_screen_status_port.xml
@@ -25,23 +25,10 @@
         android:layout_height="wrap_content"
         android:gravity="left">
 
-    <TextView
-        android:id="@+id/carrier"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
-        android:drawablePadding="4dip"
-        android:layout_marginTop="10dip"
-        android:singleLine="true"
-        android:ellipsize="marquee"
-        />
-
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="8dip"
-        android:layout_marginBottom="8dip">
+        android:layout_marginTop="8dip">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -50,7 +37,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="60sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_background"
             android:layout_marginBottom="6dip"
@@ -61,7 +48,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="60sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_foreground"
             android:layout_marginBottom="6dip"
@@ -69,19 +56,6 @@
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="22sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <LinearLayout
@@ -89,45 +63,58 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/time"
-        android:layout_marginTop="10dip">
+        android:layout_marginTop="16dip"
+        android:layout_gravity="right">
 
         <TextView
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
 
         <TextView
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="30dip"
+            android:layout_marginLeft="16dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:drawablePadding="4dip"/>
 
     </LinearLayout>
 
-    <!-- used for status such as the next alarm, and charging status.  -->
-    <TextView
-        android:id="@+id/status2"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
-        android:layout_marginTop="10dip"
-        android:drawablePadding="4dip"
-        android:visibility="gone"
-        />
-
     <TextView
         android:id="@+id/status1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="10dip"
-        android:textSize="17sp"
+        android:layout_gravity="right"
+        android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
+     <!-- used for status such as the next alarm, and charging status.  -->
+    <TextView
+        android:id="@+id/status2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="right"
+        android:layout_alignParentTop="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:layout_marginTop="4dip"
+        android:drawablePadding="4dip"
+        android:visibility="gone"
+        />
+
+
 </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 7ae357a..1e2abf9 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -28,43 +28,14 @@
     android:id="@+id/root"
     android:clipChildren="false">
 
-    <TextView
-        android:id="@+id/carrier"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentRight="true"
-        android:layout_marginTop="10dip"
-        android:layout_marginRight="8dip"
-        android:singleLine="true"
-        android:ellipsize="marquee"
-        android:gravity="right|bottom"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        />
-
-    <!-- "emergency calls only" shown when sim is missing or PUKd -->
-    <TextView
-        android:id="@+id/emergencyCallText"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/carrier"
-        android:layout_alignParentRight="true"
-        android:layout_marginTop="0dip"
-        android:layout_marginRight="8dip"
-        android:text="@string/emergency_calls_only"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="@color/white"
-       />
-
     <!-- time and date -->
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_below="@id/carrier"
-        android:layout_marginTop="52dip"
-        android:layout_marginLeft="20dip"
-        android:layout_marginBottom="8dip"
-        >
+        android:layout_alignParentRight="true"
+        android:layout_marginRight="16dip"
+        android:layout_marginTop="48dip"
+        android:layout_marginLeft="20dip">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -73,7 +44,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="72sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_background"
@@ -84,7 +55,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="72sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
@@ -92,51 +63,56 @@
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="22sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
-    <TextView
-        android:id="@+id/date"
-        android:layout_width="wrap_content"
+    <LinearLayout android:id="@+id/date_alarm_status_container"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@id/time"
-        android:layout_marginLeft="24dip"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        />
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
+        android:layout_marginTop="16dip"
+        android:layout_alignParentRight="true"
+        android:gravity="right"
+        android:orientation="horizontal">
 
-    <!-- TODO: Redo layout when we release on phones -->
-    <TextView
-        android:id="@+id/alarm_status"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="18sp"
-        android:drawablePadding="4dip"
-        android:layout_below="@id/date"
-        android:layout_marginTop="4dip"
-        android:layout_marginLeft="24dip"
-        />
+        <TextView
+            android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            />
+
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:drawablePadding="4dip"
+            android:layout_marginLeft="16dip"
+            />
+
+    </LinearLayout>
 
     <TextView
         android:id="@+id/status1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_below="@id/alarm_status"
+        android:layout_below="@id/date_alarm_status_container"
         android:layout_marginTop="4dip"
-        android:layout_marginLeft="24dip"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
+        android:layout_alignParentRight="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         />
 
@@ -146,9 +122,15 @@
         android:layout_height="wrap_content"
         android:layout_below="@id/status1"
         android:layout_marginTop="4dip"
-        android:layout_marginLeft="24dip"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
+        android:layout_alignParentRight="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
+        android:visibility="gone"
         />
 
     <TextView
@@ -156,46 +138,92 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/status2"
-        android:layout_marginLeft="24dip"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
+        android:layout_alignParentRight="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_marginTop="12dip"
         android:drawablePadding="4dip"
+        android:visibility="gone"
         />
 
-    <com.android.internal.widget.multiwaveview.MultiWaveView
-        android:id="@+id/unlock_widget"
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="300dip"
-        android:layout_alignParentBottom="true"
-
-        android:targetDrawables="@array/lockscreen_targets_when_silent"
-        android:handleDrawable="@drawable/ic_lockscreen_handle"
-        android:waveDrawable="@drawable/ic_lockscreen_outerring"
-        android:outerRadius="@*android:dimen/multiwaveview_target_placement_radius"
-        android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
-        android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
-        android:vibrationDuration="20"
-        android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
-        android:feedbackCount="3"
-        android:horizontalOffset="0dip"
-        android:verticalOffset="60dip"
-        />
-
-    <!-- emergency call button shown when sim is PUKd and tab_selector is
-         hidden -->
+    <!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
     <Button
         android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:drawableLeft="@drawable/ic_emergency"
-        android:layout_centerInParent="true"
-        android:layout_alignParentBottom="true"
-        android:layout_marginBottom="80dip"
-        style="@style/Widget.Button.Transparent"
-        android:drawablePadding="8dip"
-        android:visibility="gone"
+        android:layout_marginTop="4dip"
+        android:layout_marginRight="16dip"
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
+        android:layout_alignParentRight="true"
+        android:layout_below="@id/screenLocked"
+        style="?android:attr/buttonBarButtonStyle"
+        android:drawablePadding="4dip"
+        android:text="@string/lockscreen_emergency_call"
+        android:visibility="visible"
         />
 
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:gravity="center_horizontal">
+
+        <com.android.internal.widget.multiwaveview.MultiWaveView
+            android:id="@+id/unlock_widget"
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="300dip"
+            android:layout_alignParentBottom="true"
+
+            android:targetDrawables="@array/lockscreen_targets_when_silent"
+            android:handleDrawable="@drawable/ic_lockscreen_handle"
+            android:waveDrawable="@drawable/ic_lockscreen_outerring"
+            android:outerRadius="@dimen/multiwaveview_target_placement_radius"
+            android:snapMargin="@dimen/multiwaveview_snap_margin"
+            android:hitRadius="@dimen/multiwaveview_hit_radius"
+            android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
+            android:horizontalOffset="0dip"
+            android:verticalOffset="60dip"
+            android:feedbackCount="3"
+            android:vibrationDuration="20"
+            />
+
+        <TextView
+            android:id="@+id/carrier"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_marginBottom="8dip"
+            android:gravity="center_horizontal"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
+            />
+
+        <!-- "emergency calls only" shown when sim is missing or PUKd -->
+        <TextView
+            android:id="@+id/emergencyCallText"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_above="@id/carrier"
+            android:gravity="center_horizontal"
+            android:layout_marginTop="0dip"
+            android:layout_marginRight="8dip"
+            android:text="@string/emergency_calls_only"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
+            />
+
+    </RelativeLayout>
+
 </RelativeLayout>
 
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 d45cc85..5588adc 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -32,8 +32,9 @@
     <Space android:height="20dip"/>
 
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
-        android:layout_marginTop="56dip"
-        android:layout_marginBottom="8dip">
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="8dip"
+        android:layout_gravity="right">
 
        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -42,7 +43,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="72sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_background"
@@ -53,7 +54,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="72sp"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
@@ -61,67 +62,69 @@
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="22sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            android:visibility="gone"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <TextView
         android:id="@+id/date"
         android:layout_below="@id/time"
         android:layout_marginTop="6dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:layout_gravity="left"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/alarm_status"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="18sp"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         android:layout_marginTop="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/status1"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/status2"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/screenLocked"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:gravity="center"
         android:layout_marginTop="4dip"
         android:drawablePadding="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <Space android:height="20dip"/>
 
-    <LinearLayout android:orientation="horizontal" >
+    <LinearLayout android:orientation="vertical"
+        android:layout_gravity="right"
+        android:gravity="fill_horizontal">
 
          <TextView
             android:id="@+id/carrier"
@@ -130,19 +133,10 @@
             android:layout_alignParentTop="true"
             android:singleLine="true"
             android:ellipsize="marquee"
-            android:layout_gravity="bottom|left"
+            android:layout_gravity="right"
             android:textAppearance="?android:attr/textAppearanceMedium"
-        />
-
-        <Button
-            android:id="@+id/emergencyCallButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:drawableLeft="@drawable/ic_emergency"
-            style="@style/Widget.Button.Transparent"
-            android:drawablePadding="8dip"
-            android:layout_marginRight="80dip"
-            android:visibility="gone"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
         />
 
         <!-- "emergency calls only" shown when sim is missing or PUKd -->
@@ -152,14 +146,28 @@
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
             android:layout_marginTop="20dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:text="@string/emergency_calls_only"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="@color/white"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
+            android:layout_gravity="right"
+        />
+
+        <Button
+            android:id="@+id/emergencyCallButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableLeft="@drawable/lockscreen_emergency_button"
+            android:text="@string/lockscreen_emergency_call"
+            style="?android:attr/buttonBarButtonStyle"
+            android:drawablePadding="8dip"
+            android:visibility="visible"
+            android:layout_gravity="right"
         />
     </LinearLayout>
 
-    <Space android:height="20dip"/>
-
     <!-- Column 1 -->
     <Space android:width="20dip" android:layout_columnWeight="1" android:layout_rowSpan="10" />
 
@@ -173,12 +181,12 @@
         android:targetDrawables="@array/lockscreen_targets_when_silent"
         android:handleDrawable="@drawable/ic_lockscreen_handle"
         android:waveDrawable="@drawable/ic_lockscreen_outerring"
-        android:outerRadius="@*android:dimen/multiwaveview_target_placement_radius"
-        android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
-        android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
-        android:vibrationDuration="20"
+        android:outerRadius="@dimen/multiwaveview_target_placement_radius"
+        android:snapMargin="@dimen/multiwaveview_snap_margin"
+        android:hitRadius="@dimen/multiwaveview_hit_radius"
         android:topChevronDrawable="@drawable/ic_lockscreen_chevron_up"
         android:feedbackCount="3"
+        android:vibrationDuration="20"
         android:horizontalOffset="0dip"
         android:verticalOffset="0dip"
         />
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index d52bc57..d0538dd 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -26,7 +26,7 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:rowCount="9">
+    android:rowCount="7">
 
     <!-- Column 0: Time, date and status -->
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
@@ -44,7 +44,7 @@
             android:singleLine="true"
             android:ellipsize="none"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_background"
             />
@@ -55,7 +55,7 @@
             android:singleLine="true"
             android:ellipsize="none"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:layout_marginBottom="6dip"
             android:layout_alignLeft="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
@@ -68,8 +68,10 @@
         android:id="@+id/date"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
         />
 
@@ -77,8 +79,10 @@
         android:id="@+id/alarm_status"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
         android:drawablePadding="4dip"
         />
@@ -87,49 +91,58 @@
         android:id="@+id/status1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
         />
 
-    <TextView
-        android:id="@+id/status2"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
-        android:layout_gravity="right"
-        android:drawablePadding="4dip"
-        android:visibility="gone"
-        />
-
-    <Space android:layout_rowWeight="1" android:layout_columnWeight="1" />
+    <!-- TODO: remove hard coded height since layout_rowWeight doesn't seem to be working -->
+    <Space
+    android:layout_height="43dip"
+    android:layout_gravity="fill"
+    android:layout_rowWeight="1" android:layout_columnWeight="1" />
 
     <TextView android:id="@+id/carrier"
         android:layout_gravity="right"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
         android:singleLine="true"
         android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         />
 
-    <Button android:id="@+id/emergencyCallButton"
-        android:layout_gravity="right"
-        style="@*android:style/Widget.Button.Transparent"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
-        android:text="@string/lockscreen_emergency_call"
-        android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
-        android:drawablePadding="0dip"
-    />
+    <LinearLayout
+        style="?android:attr/buttonBarStyle"
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="right">
 
-    <Button android:id="@+id/forgotPatternButton"
-        android:layout_gravity="right"
-        style="@*android:style/Widget.Button.Transparent"
-        android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
-        android:text="@*android:string/lockscreen_forgot_pattern_button_text"
-        android:drawableLeft="@*android:drawable/lockscreen_forgot_password_button"
-        android:drawablePadding="0dip"
-    />
+        <Button android:id="@+id/emergencyCallButton"
+            style="?android:attr/buttonBarButtonStyle"
+            android:layout_gravity="right"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:text="@string/lockscreen_emergency_call"
+            android:drawableLeft="@drawable/lockscreen_emergency_button"
+            android:drawablePadding="0dip"
+        />
+
+        <Button android:id="@+id/forgotPatternButton"
+            style="?android:attr/buttonBarButtonStyle"
+            android:layout_gravity="right"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:text="@string/lockscreen_forgot_pattern_button_text"
+            android:drawableLeft="@drawable/lockscreen_forgot_password_button"
+            android:drawablePadding="0dip"
+        />
+    </LinearLayout>
 
     <!-- Column 1: lock pattern -->
     <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
@@ -139,6 +152,6 @@
          android:layout_marginRight="8dip"
          android:layout_marginBottom="8dip"
          android:layout_marginLeft="8dip"
-         android:layout_rowSpan="9"/>
+         android:layout_rowSpan="7"/>
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index dd68d82..774f830 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -30,27 +30,28 @@
 
     <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">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
-        <TextView android:id="@*android:id/timeDisplayBackground"
+        <TextView android:id="@+id/timeDisplayBackground"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="@*android:dimen/keyguard_pattern_unlock_clock_font_size"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
-            android:textColor="@*android:color/lockscreen_clock_background"
+            android:textColor="@color/lockscreen_clock_background"
             />
 
-        <TextView android:id="@*android:id/timeDisplayForeground"
+        <TextView android:id="@+id/timeDisplayForeground"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="@*android:dimen/keyguard_pattern_unlock_clock_font_size"
+            android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
@@ -60,14 +61,17 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right">
+        android:layout_gravity="right"
+        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@*android:dimen/keyguard_pattern_unlock_status_line_font_size"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             />
 
         <TextView
@@ -75,8 +79,10 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="16dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@*android:dimen/keyguard_pattern_unlock_status_line_font_size"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:drawablePadding="4dip"
             />
 
@@ -85,22 +91,31 @@
 
     <TextView
         android:id="@+id/status1"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@*android:dimen/keyguard_pattern_unlock_status_line_font_size"
-        android:drawablePadding="4dip"
         android:layout_gravity="right"
+        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawablePadding="4dip"
         />
 
     <TextView
         android:id="@+id/status2"
-        android:layout_alignParentTop="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@*android:dimen/keyguard_pattern_unlock_status_line_font_size"
-        android:drawablePadding="4dip"
         android:layout_gravity="right"
+        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawablePadding="4dip"
         android:visibility="gone"
         />
 
+    <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to
+    the pattern view for it to compute its size. This is an unusual case, caused by
+    LockPatternView's requirement to maintain a square aspect ratio based on the width
+    of the screen. -->
     <com.android.internal.widget.LockPatternView
         android:id="@+id/lockPattern"
         android:layout_width="match_parent"
@@ -109,6 +124,8 @@
         android:layout_marginRight="8dip"
         android:layout_marginBottom="4dip"
         android:layout_marginLeft="8dip"
+        android:layout_gravity="center|bottom"
+        android:layout_rowWeight="1"
      />
 
     <TextView
@@ -116,7 +133,7 @@
         android:layout_gravity="center_horizontal"
         android:singleLine="true"
         android:ellipsize="marquee"
-        android:textSize="@*android:dimen/keyguard_pattern_unlock_status_line_font_size"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:textAppearance="?android:attr/textAppearanceMedium"
     />
 
@@ -124,25 +141,29 @@
     <LinearLayout
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_gravity="center">
+        style="?android:attr/buttonBarStyle"
+        android:gravity="center"
+        android:weightSum="2">
 
         <Button android:id="@+id/emergencyCallButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
-            style="@style/Widget.Button.Transparent"
-            android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="?android:attr/buttonBarButtonStyle"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:text="@string/lockscreen_emergency_call"
             android:drawableLeft="@drawable/lockscreen_emergency_button"
             android:drawablePadding="0dip"
         />
 
         <Button android:id="@+id/forgotPatternButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
-            style="@style/Widget.Button.Transparent"
-            android:textSize="@dimen/keyguard_pattern_unlock_status_line_font_size"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="?android:attr/buttonBarButtonStyle"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:text="@string/lockscreen_forgot_pattern_button_text"
             android:drawableLeft="@drawable/lockscreen_forgot_password_button"
             android:drawablePadding="0dip"
diff --git a/core/res/res/layout/number_picker.xml b/core/res/res/layout/number_picker.xml
index 807daf2..f2f524c 100644
--- a/core/res/res/layout/number_picker.xml
+++ b/core/res/res/layout/number_picker.xml
@@ -23,6 +23,8 @@
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         style="?android:attr/numberPickerUpButtonStyle"
+        android:paddingTop="22dip"
+        android:paddingBottom="22dip"
         android:contentDescription="@string/number_picker_increment_button" />
 
     <EditText android:id="@+id/numberpicker_input"
@@ -34,6 +36,8 @@
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         style="?android:attr/numberPickerDownButtonStyle"
+        android:paddingTop="22dip"
+        android:paddingBottom="22dip"
         android:contentDescription="@string/number_picker_decrement_button" />
 
 </merge>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 9742b94..2392618 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -46,7 +46,7 @@
     <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
-                  style="?android:attr/actionBarStyle"
+                  style="?android:attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
 </LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 086acdd..19b861c 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -50,7 +50,7 @@
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:layout_alignParentBottom="true"
-                  style="?android:attr/actionBarStyle"
+                  style="?android:attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
 </RelativeLayout>
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 7918a3f..790ac6b 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -23,36 +23,58 @@
     android:id="@+id/search_bar"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="horizontal"
+    android:orientation="vertical"
+    android:background="@color/transparent"
     android:focusable="true"
-    android:background="?android:attr/actionModeBackground"
     android:descendantFocusability="afterDescendants">
 
-    <RelativeLayout
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        >
+        android:background="?android:attr/actionModeBackground"
+        android:orientation="horizontal">
 
-        <ImageView
-            android:id="@+id/search_app_icon"
-            android:layout_height="48dip"
-            android:layout_width="48dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip"
-            android:layout_gravity="center_vertical"
-            android:layout_alignParentLeft="true"
-        />
-        <SearchView
-            android:id="@+id/search_view"
-            android:layout_width="match_parent"
+        <!-- Grouped to allow tapping on either item to exit search mode -->
+        <LinearLayout
+            android:id="@id/closeButton"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:maxWidth="600dip"
-            android:iconifiedByDefault="false"
-            android:layout_alignParentRight="true"
-            android:layout_gravity="center_vertical|right"
+            android:orientation="horizontal"
+            android:focusable="true"
+            android:background="?android:attr/selectableItemBackground">
+
+            <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:src="?android:attr/homeAsUpIndicator"/>
+
+            <ImageView
+                android:id="@+id/search_app_icon"
+                android:layout_height="48dip"
+                android:layout_width="48dip"
+                android:layout_gravity="center_vertical"
             />
 
-    </RelativeLayout>
+        </LinearLayout>
 
+        <!-- Actual search view with search icon, text field, close
+            and voice buttons -->
+        <SearchView
+            android:id="@+id/search_view"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:maxWidth="600dip"
+            android:iconifiedByDefault="false"
+            android:layout_gravity="center_vertical"
+            />
+
+    </LinearLayout>
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:scaleType="fitXY"
+        android:src="@drawable/title_bar_shadow"/>
 </view>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 99fdf5b..475aa59 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -74,7 +74,6 @@
                 android:id="@+id/search_app_icon"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginRight="7dip"
                 android:layout_gravity="center_vertical"
                 android:src="?android:attr/searchViewSearchIcon"
             />
diff --git a/core/res/res/layout/ssl_certificate.xml b/core/res/res/layout/ssl_certificate.xml
new file mode 100644
index 0000000..7206077
--- /dev/null
+++ b/core/res/res/layout/ssl_certificate.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical" >
+
+        <!-- Placeholder for the success message or one or more warnings -->
+        <LinearLayout
+            android:id="@+id/placeholder"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginTop="12dip"
+            android:orientation="vertical" />
+
+        <!-- Dialog-title line separator -->
+        <ImageView
+            android:id="@+id/title_separator"
+            android:src="@android:drawable/divider_horizontal_dark"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scaleType="fitXY"
+            android:layout_weight="1"
+            android:gravity="fill_horizontal"
+            android:layout_marginRight="20dip"
+            android:layout_marginLeft="20dip"
+            android:layout_marginBottom="12dip" />
+
+        <TableLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <!-- Issued to: -->
+            <TextView
+                android:id="@+id/issued_to_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/issued_to"
+                android:textStyle="bold"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Common name: -->
+            <TextView
+                android:id="@+id/to_common_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/common_name"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/to_common"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Organization: -->
+            <TextView
+                android:id="@+id/to_org_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/org_name"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/to_org"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Organizational unit: -->
+            <TextView
+                android:id="@+id/to_org_unit_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/org_unit"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/to_org_unit"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="12dip" />
+
+            <!-- Issued by: -->
+            <TextView
+                android:id="@+id/issued_to_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/issued_by"
+                android:textStyle="bold"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Common name: -->
+            <TextView
+                android:id="@+id/by_common_header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/common_name"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/by_common"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Organization: -->
+            <TextView
+                android:id="@+id/by_org_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/org_name"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/by_org"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Organizational unit: -->
+            <TextView
+                android:id="@+id/by_org_unit_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/org_unit"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/by_org_unit"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="12dip" />
+
+            <!-- Validity Dates: -->
+            <TextView
+                android:id="@+id/validity_header"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/validity_period"
+                android:textStyle="bold"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Issued On: -->
+            <TextView
+                android:id="@+id/issued_on_header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/issued_on"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/issued_on"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="10dip" />
+
+            <!-- Expires On: -->
+            <TextView
+                android:id="@+id/expires_on_header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/expires_on"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip" />
+
+            <TextView
+                android:id="@+id/expires_on"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="left"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="12dip" />
+
+        </TableLayout>
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a326712..648f665 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"شهادة الأمان"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"هذه الشهادة صالحة."</string>
+    <string name="issued_to" msgid="9032338008819841339">"تم الإصدار إلى:"</string>
+    <string name="common_name" msgid="5745530093500062357">"الاسم الشائع:"</string>
+    <string name="org_name" msgid="8868889052889991293">"المؤسسة:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"وحدة تنظيمية:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"تم الإصدار بواسطة:"</string>
+    <string name="validity_period" msgid="57988851973181309">"الصلاحية:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"تم الإصدار في:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"تنتهي الصلاحية في:"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5633807..6401b1c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Сертификат за сигурност"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Сертификатът е валиден."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Издаден на:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Общо име:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Организация:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Организационна единица:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Издаден от:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Валидност:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Издаден на:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Изтича на:"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e812217..a2e75d3e 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificat de seguretat"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Aquest certificat és vàlid."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Emès per a:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nom comú:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organització:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unitat organitzativa:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Publicat per:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validesa:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Publicat el:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Caduca el:"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index d10e1b4..ca3035d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certifikát zabezpečení"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Tento certifikát je platný."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Vydáno komu:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Běžný název:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizace:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizační jednotka:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Vydal:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Platnost:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Datum vydání:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Platnost vyprší:"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a7f62ec..7153416 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Sikkerhedscertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Dette certifikat er gyldigt."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Udstedt til:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Fællesnavn:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisation:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organisatorisk enhed:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Udstedt af:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Gyldighed:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Udstedt den:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Udløber den:"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index afa606f..9753482 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Sicherheitszertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Dies ist ein gültiges Zertifikat."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Ausgegeben an:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Allgemeiner Name."</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisation:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organisationseinheit:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Ausgegeben von:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Gültigkeit:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Ausgegeben am:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Läuft ab am:"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 65d04b4..81b9107 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Πιστοποιητικό ασφαλείας"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Αυτό το πιστοποιητικό είναι έγκυρο."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Εκδόθηκε στις:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Κοινό όνομα:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Οργανισμός:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Μονάδα οργάνωσης:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Εκδόθηκε:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Ισχύς:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Εκδόθηκε στις:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Λήγει:"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index c048b99..7c2cc2f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificado de seguridad"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Este certificado es válido."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Emitido para:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nombre común:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organización:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Departamento:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Emitido por:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validez:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Fecha de emisión:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Fecha de caducidad:"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4ea2aa7..48ad6f1 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"گواهی امنیتی"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"این گواهی معتبر است."</string>
+    <string name="issued_to" msgid="9032338008819841339">"صدور برای:"</string>
+    <string name="common_name" msgid="5745530093500062357">"نام عادی:"</string>
+    <string name="org_name" msgid="8868889052889991293">"سازمان:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"واحد سازمانی:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"صدور توسط:"</string>
+    <string name="validity_period" msgid="57988851973181309">"اعتبار:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"صدور در:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"تاریخ انقضا:"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 50c0268..5ddbb45 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Suojausvarmenne"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Varmenne on voimassa."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Varmenteen saaja:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Yleinen nimi:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisaatio:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organisaatioyksikkö:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Myöntäjä:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Voimassa:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Myönnetty:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Vanhenee:"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8d95338..fe1dd13 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificat de sécurité"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Ce certificat est valide."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Émis à :"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nom commun :"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisation :"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unité d\'organisation :"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Émis par :"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validité :"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Émis le :"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Expire le :"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 71d49cc..391fd08 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certifikat o sigurnosti"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Ovaj je certifikat valjan."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Izdano do:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Zajednički naziv:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Tvrtka ili ustanova:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizacijska jedinica:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Izdao:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Vrijedi do:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Izdano dana:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Ističe dana:"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index bbe635f..c5e16cf 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Biztonsági tanúsítvány"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"A tanúsítvány érvényes."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Kiállítva a következőnek:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Név:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Szervezet:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Szervezeti egység:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Kiállította:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Érvényesség:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Kiállítva:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Lejár:"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 53d245a..4e7504a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Sertifikat keamanan"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sertifikat ini valid."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Diterbitkan ke:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nama umum:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisasi:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unit organisasi:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Diterbitkan oleh:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validitas:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Diterbitkan pada:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Kedaluwarsa pada:"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3c9d909..10d1787 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificato di protezione"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Questo certificato è valido."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Rilasciato a:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nome comune:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizzazione:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unità organizzativa:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Rilasciato da:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validità:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Rilasciato il:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Scade il:"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 71aa9f1..3fce696 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"אישור אבטחה"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"אישור זה תקף."</string>
+    <string name="issued_to" msgid="9032338008819841339">"הופק עבור:"</string>
+    <string name="common_name" msgid="5745530093500062357">"שם משותף:"</string>
+    <string name="org_name" msgid="8868889052889991293">"ארגון:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"יחידה ארגונית:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"הופק על ידי:"</string>
+    <string name="validity_period" msgid="57988851973181309">"חוקיות:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"הונפק בתאריך:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"פג תוקף ב:"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 388b47b..9771a29 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"セキュリティ証明書"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"この証明書は有効です。"</string>
+    <string name="issued_to" msgid="9032338008819841339">"発行先:"</string>
+    <string name="common_name" msgid="5745530093500062357">"共通名:"</string>
+    <string name="org_name" msgid="8868889052889991293">"組織:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"組織単位:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"発行者:"</string>
+    <string name="validity_period" msgid="57988851973181309">"有効期間:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"発行:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"有効期限:"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f7e1a75..a50f743 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"보안 인증서"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"유효한 인증서입니다."</string>
+    <string name="issued_to" msgid="9032338008819841339">"발급 대상:"</string>
+    <string name="common_name" msgid="5745530093500062357">"일반 이름:"</string>
+    <string name="org_name" msgid="8868889052889991293">"조직:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"조직 구성 단위:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"발급 기관:"</string>
+    <string name="validity_period" msgid="57988851973181309">"유효성:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"발급 날짜:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"만료 날짜:"</string>
 </resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index b8ce9b4..ec2313c 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -31,8 +31,14 @@
 
     <!-- Default height of an action bar. -->
     <dimen name="action_bar_default_height">40dip</dimen>
+    <!-- Vertical padding around action bar icons. -->
+    <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
+    <!-- Text size for action bar titles -->
+    <dimen name="action_bar_title_text_size">16dp</dimen>
+    <!-- Text size for action bar subtitles -->
+    <dimen name="action_bar_subtitle_text_size">12dp</dimen>
 
-    <!-- Size of clock font in LockScreen. -->
-    <dimen name="keyguard_pattern_unlock_clock_font_size">80sp</dimen>
+    <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
+    <dimen name="keyguard_lockscreen_clock_font_size">70sp</dimen>
 
 </resources>
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
index 55eb145..4f49135 100644
--- a/core/res/res/values-large/dimens.xml
+++ b/core/res/res/values-large/dimens.xml
@@ -43,10 +43,4 @@
 
     <!-- Preference UI dimensions for larger screens. -->
     <dimen name="preference_widget_width">56dp</dimen>
-    <!-- The maximum number of action buttons that should be permitted within
-         an action bar/action mode. This will be used to determine how many
-         showAsAction="ifRoom" items can fit. "always" items can override this. -->
-    <integer name="max_action_buttons">5</integer>
-    <!-- Default height of an action bar. -->
-    <dimen name="action_bar_default_height">56dip</dimen>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 549641f..d99d0ec 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Saugos sertifikatas"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Šis sertifikatas galioja."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Išduota:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Bendras pavadinimas:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizacija:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizacinis vienetas:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Išdavė:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Galiojimas:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Išduota:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Galiojimas baigiasi:"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e32df3b..553f3ee 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Drošības sertifikāts"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sertifikāts ir derīgs."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Izdots:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Kopējais nosaukums:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizācija:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizācijas vienība:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Izsniedzējs:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Derīgums:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Izsniegšanas datums:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Derīguma termiņš:"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 15896ae..f432672 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1127,4 +1127,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Sijil keselamatan"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sijil ini sah."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Dikeluarkan kepada:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nama biasa:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisasi:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unit Organisasi:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Dikeluarkan oleh:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Kesahan:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Dikeluarkan pada:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Tamat tempoh pada:"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ca6d608..aca95fd 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Sikkerhetssertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sertifikatet er gyldig."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Utstedt til:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Ordinært navn:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisasjon:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organisasjonsenhet:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Utstedt av:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Gyldighet:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Utstedt:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Utløper den:"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8f54331..5fe75fc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Beveiligingscertificaat"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Dit certificaat is geldig."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Uitgegeven voor:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Algemene naam:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisatie:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organisatie-eenheid:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Uitgegeven door:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Geldigheid:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Uitgegeven op:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Verloopt op:"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 10bc614..0221da7 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certyfikat zabezpieczeń"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Ten certyfikat jest prawidłowy."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Otrzymujący:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nazwa pospolita:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizacja:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Jednostka organizacyjna:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Wystawca:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Poprawność:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Data wystawienia:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Wygasa:"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a17277e..09f0876 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificado de segurança"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Este certificado é válido."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Emitido para:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nome comum:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organização:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unidade organizacional:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Emitido por:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validade:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Emitido em:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Expira em:"</string>
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index b1fa217..c6fea8e 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1223,4 +1223,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificat da segirezza"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Quest certificat è valid."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Emess a:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Num general:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisaziun:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unitad d\'organisaziun:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Emess da:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validitad:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Emess ils:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Scroda ils:"</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 404570a..25fdb54 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificat de securitate"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Certificatul este valid."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Emis de:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nume comun:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizaţie:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizaţie:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Emis de:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Validitate:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Emis pe:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Expiră pe:"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 44cc9df..170ee85 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Сертификат безопасности"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Этот сертификат действителен."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Владелец сертификата:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Стандартное имя:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Организация:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Подразделение организации:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Выпущен:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Срок действия:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Дата издания:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Дата окончания действия:"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index dc962b1..4ef89b7 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certifikát zabezpečenia"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Certifikát je platný."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Vydané pre:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Bežný názov:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizácia:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizačná jednotka:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Vydal:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Platnosť:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Dátum vydania:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Platnosť vyprší:"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e613bf0..86546e02 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Varnostno potrdilo"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Potrdilo je veljavno."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Izdano za:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Pogosto ime:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organizacija:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organizacijska enota:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Izdal:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Veljavnost:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Izdano:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Velja do:"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 455e1a9..2fd051c 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Безбедносни сертификат"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Овај сертификат је важећи."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Издато за:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Уобичајени назив:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Организација:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Организациона јединица:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Издавалац:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Ваљаност:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Издато дана:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Датум истека:"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 22ca7e2..a17dc8d 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Säkerhetscertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Detta certifikat är giltigt."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Utfärdat till:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Nätverksnamn:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Organisation:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Organisationsenhet:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Utfärdat av:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Giltighet:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Utfärdat den:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Upphör att gälla:"</string>
 </resources>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index d6a0cdd..13bbac6 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -23,9 +23,6 @@
     <!-- see comment in values/config.xml -->
     <integer name="config_longPressOnPowerBehavior">2</integer>
 
-    <!-- Show sliding tab before lockscreen -->
-    <bool name="config_enableSlidingTabFirst">false</bool>
-
     <!-- Enable lockscreen rotation -->
     <bool name="config_enableLockScreenRotation">true</bool>
 
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 150b6d4..9ffe6b1 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -25,6 +25,19 @@
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
 
+    <!-- The maximum number of action buttons that should be permitted within
+         an action bar/action mode. This will be used to determine how many
+         showAsAction="ifRoom" items can fit. "always" items can override this. -->
+    <integer name="max_action_buttons">5</integer>
+    <!-- Default height of an action bar. -->
+    <dimen name="action_bar_default_height">56dip</dimen>
+    <!-- Vertical padding around action bar icons. -->
+    <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
+    <!-- Text size for action bar titles -->
+    <dimen name="action_bar_title_text_size">18dp</dimen>
+    <!-- Text size for action bar subtitles -->
+    <dimen name="action_bar_subtitle_text_size">14dp</dimen>
+
     <!-- Size of clock font in LockScreen. -->
     <dimen name="keyguard_pattern_unlock_clock_font_size">98sp</dimen>
 
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b6de800..2eb1b79 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"ใบรับรองความปลอดภัย"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"ใบรับรองนี้ใช้งานได้"</string>
+    <string name="issued_to" msgid="9032338008819841339">"ออกให้แก่:"</string>
+    <string name="common_name" msgid="5745530093500062357">"ชื่อทั่วไป:"</string>
+    <string name="org_name" msgid="8868889052889991293">"องค์กร:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"หน่วยองค์กร:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"ออกโดย:"</string>
+    <string name="validity_period" msgid="57988851973181309">"อายุการใช้งาน:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"ออกเมื่อ:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"หมดอายุวันที่:"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bba5e2f..760724b 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Certificate na pangseguridad"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Wasto ang certificate na ito."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Ibinigay kay:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Karaniwang pangalan:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Samahan:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Unit na pangsamahan:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Ibinigay ni:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Pagpapatunay:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Ibinigay noong:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Mag-e-expire sa:"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 3bce91b..f9f2a16 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Güvenlik sertifikası"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Bu sertifika geçerli."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Alıcı:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Ortak ad:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Kuruluş:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Kuruluş birimi:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Yayınlayan:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Geçerlilik:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Yayınlanma tarihi:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Sona erme tarihi:"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3bb3788..02636af 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Сертифікат безпеки"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Цей сертифікат є дійсним."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Кому видано:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Загальне ім\'я:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Організація:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Організац. підрозділ:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Ким видано:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Чинність:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Дата видачі:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Діє до:"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index db408d8..1b1c8ba 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1106,4 +1106,14 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="5226747157992111668">"Chứng chỉ bảo mật"</string>
+    <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Chứng chỉ này hợp lệ."</string>
+    <string name="issued_to" msgid="9032338008819841339">"Cấp cho:"</string>
+    <string name="common_name" msgid="5745530093500062357">"Tên chung:"</string>
+    <string name="org_name" msgid="8868889052889991293">"Tổ chức:"</string>
+    <string name="org_unit" msgid="4489056376307768196">"Đơn vị tổ chức:"</string>
+    <string name="issued_by" msgid="6959484326943152487">"Cấp bởi:"</string>
+    <string name="validity_period" msgid="57988851973181309">"Tính hợp lệ:"</string>
+    <string name="issued_on" msgid="2082890654801808368">"Cấp vào:"</string>
+    <string name="expires_on" msgid="8061200430557020704">"Hết hạn vào:"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 58d25d6..fd61cfd 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -596,6 +596,11 @@
         <attr name="actionOverflowButtonStyle" format="reference" />
         <!-- Reference to a style for the Action Bar -->
         <attr name="actionBarStyle" format="reference" />
+        <!-- Reference to a style for the split Action Bar. This style
+             controls the split component that holds the menu/action
+             buttons. actionBarStyle is still used for the primary
+             bar. -->
+        <attr name="actionBarSplitStyle" format="reference" />
         <!-- Size of the Action Bar, including the contextual
              bar used to present Action Modes. -->
         <attr name="actionBarSize" format="dimension" >
@@ -1967,6 +1972,24 @@
             <!-- Locale -->
             <enum name="locale" value="3" />
         </attr>
+        <!-- Direction of the text. A heuristic is used to determine the resolved text direction
+             of paragraphs. -->
+        <attr name="textDirection" format="integer">
+            <!-- Default -->
+            <enum name="inherit" value="0" />
+            <!-- Default for the root view. The first strong directional character determines the
+                 paragraph direction.  If there is o strong directional character, the paragraph
+                 direction is the view’s resolved layout direction. -->
+            <enum name="firstStrong" value="1" />
+            <!-- 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. -->
+            <enum name="anyRtl" value="2" />
+            <!-- The text direction is left to right. -->
+            <enum name="ltr" value="3" />
+            <!-- The text direction is right to left. -->
+            <enum name="rtl" value="4" />
+        </attr>
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2125,6 +2148,12 @@
         <!--  Specifies extra space on the bottom side of this view.
               This space is outside this view's bounds. -->
         <attr name="layout_marginBottom" format="dimension"  />
+        <!--  Specifies extra space on the start side of this view.
+              This space is outside this view's bounds. -->
+        <attr name="layout_marginStart" format="dimension"  />
+        <!--  Specifies extra space on the end side of this view.
+              This space is outside this view's bounds. -->
+        <attr name="layout_marginEnd" format="dimension"  />
     </declare-styleable>
 
     <!-- Use <code>input-method</code> as the root tag of the XML resource that
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f7974e9..03b332e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -235,12 +235,13 @@
     <attr name="vmSafeMode" format="boolean" />
 
     <!-- <p>Flag indicating whether the application's rendering should be hardware
-         accelerated if possible. This flag is turned off by default, both for
-         applications and activities.</p>
+         accelerated if possible. This flag is turned on by default for applications
+         that are targeting {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}
+         or later.</p>
          <p>This flag can be set on the application and any activity declared
          in the manifest. When enabled for the application, each activity is
          automatically assumed to be hardware accelerated. This flag can be
-         overriden in the activity tags, either turning it off (if on for the
+         overridden in the activity tags, either turning it off (if on for the
          application) or on (if off for the application.)</p>
          <p>When this flag is turned on for an activity (either directly or via
          the application tag), every window created from the activity, including
@@ -1020,7 +1021,7 @@
          {@link #AndroidManifest manifest} tag. -->
     <declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest">
         <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
-             this is the new way to specify the screens an application is
+             this is the new way to specify the minimum screen size an application is
              compatible with.  This attribute provides the required minimum
              "smallest screen width" (as per the -swNNNdp resource configuration)
              that the application can run on.  For example, a typical phone
@@ -1031,17 +1032,15 @@
              or xlargeScreens attributes will be used instead. -->
         <attr name="requiresSmallestWidthDp" format="integer" />
         <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
-             this is the new way to specify the screens an application is
+             this is the new way to specify the largest screens an application is
              compatible with.  This attribute provides the maximum
              "smallest screen width" (as per the -swNNNdp resource configuration)
              that the application is designed for.  If this value is smaller than
              the "smallest screen width" of the device it is running on, the user
-             will of offered to run it in a compatibility mode that emulates a
-             smaller screen.  Currently the compatibility mode only emulates
-             phone screens, so it will not be used it the application provides
-             a requiresSmallestWidthDp that is larger than 320.  Typical values
-             used with this attribute are 320 for a phone screen, 600 for a
-             7" tablet, and 720 for a 10" tablet. -->
+             is offered to run it in a compatibility mode that emulates a
+             smaller screen and zooms it to fit the screen. Currently the compatibility mode only
+             emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+             value for compatibleWidthLimitDp is larger than 320. -->
         <attr name="compatibleWidthLimitDp" format="integer" />
         <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
              this is the new way to specify the screens an application is
@@ -1050,9 +1049,9 @@
              that the application can work well on.  If this value is smaller than
              the "smallest screen width" of the device it is running on, the
              application will be forced in to screen compatibility mode with
-             no way for the user to turn it off.  Currently the compatibility mode
-             only emulates phone screens, so even if this value is larger than 320
-             the width the app runs in will be a 320 phone dimension. -->
+             no way for the user to turn it off. Currently the compatibility mode only
+             emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+             value for largestWidthLimitDp is larger than 320. -->
         <attr name="largestWidthLimitDp" format="integer" />
         <!-- Indicates whether the application supports smaller screen form-factors.
              A small screen is defined as one with a smaller aspect ratio than
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 52b00c6..827153e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3,16 +3,16 @@
 /*
 ** 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 -->
@@ -54,25 +54,25 @@
          connected.  If you use the ims apn DCT will block
          any other apn from connecting until ims apn is connected-->
     <bool name="ImsConnectedDefaultValue">false</bool>
-    
+
     <!-- Flag indicating whether the surface flinger is inefficient
          at performing a blur.  Used by parts of the UI to turn off
          the blur effect where it isn't worth the performance hit. -->
     <bool name="config_sf_slowBlur">false</bool>
-    
+
     <!-- The duration (in milliseconds) of a short animation. -->
     <integer name="config_shortAnimTime">200</integer>
-    
+
     <!-- The duration (in milliseconds) of a medium-length animation. -->
     <integer name="config_mediumAnimTime">400</integer>
-    
+
     <!-- The duration (in milliseconds) of a long animation. -->
     <integer name="config_longAnimTime">500</integer>
 
     <!-- The duration (in milliseconds) of the activity open/close and fragment open/close animations. -->
     <integer name="config_activityShortDur">150</integer>
     <integer name="config_activityDefaultDur">220</integer>
-    
+
     <!-- Duration for the dim animation behind a dialog.  This may be either
          a percentage, which is relative to the duration of the enter/open
          animation of the window being shown that is dimming behind, or it may
@@ -83,11 +83,11 @@
          maximum (let them grow as large as the screen).  Actual values are
          specified for -large and -xlarge configurations. -->
     <dimen name="config_prefDialogWidth">320dp</dimen>
-    
+
     <!-- Whether dialogs should close automatically when the user touches outside
          of them.  This should not normally be modified. -->
     <bool name="config_closeDialogWhenTouchOutside">false</bool>
-    
+
     <!-- The duration (in milliseconds) that the radio will scan for a signal
          when there's no network connection. If the scan doesn't timeout, use zero -->
     <integer name="config_radioScanningTimeout">0</integer>
@@ -98,7 +98,7 @@
     <!-- This string array should be overridden by the device to present a list of network
          attributes.  This is used by the connectivity manager to decide which networks can coexist
          based on the hardware -->
-    <!-- An Array of "[Connection name],[ConnectivityManager connection type],
+    <!-- An Array of "[Connection name],[ConnectivityManager.TYPE_xxxx],
          [associated radio-type],[priority],[restoral-timer(ms)],[dependencyMet]  -->
     <!-- the 5th element "resore-time" indicates the number of milliseconds to delay
          before automatically restore the default connection.  Set -1 if the connection
@@ -115,6 +115,14 @@
         <item>"mobile_cbs,12,0,2,60000,true"</item>
     </string-array>
 
+    <!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only
+         be controlled by systemOrSignature apps.  -->
+    <integer-array translatable="false" name="config_protectedNetworks">
+        <item>10</item>
+        <item>11</item>
+        <item>12</item>
+    </integer-array>
+
     <!-- This string array should be overridden by the device to present a list of radio
          attributes.  This is used by the connectivity manager to decide which networks can coexist
          based on the hardware -->
@@ -154,20 +162,16 @@
     <string-array translatable="false" name="config_tether_dhcp_range">
     </string-array>
 
-    <!-- Regex array of allowable upstream ifaces for tethering - for example if you want
-         tethering on a new interface called "foo2" add <item>"foo\\d"</item> to the array -->
-    <!-- Interfaces will be prioritized according to the order listed -->
-    <string-array translatable="false" name="config_tether_upstream_regexs">
-    </string-array>
-
     <!-- Regex of wired ethernet ifaces -->
     <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
 
-    <!-- Boolean indicating if we require the use of DUN on mobile for tethering.
-         Note that this defaults to false so that if you move to a carrier that
-         hasn't configured anything tethering will still work.  If you'd rather
-         make the device untetherable on unconfigured devices, set to true -->
-    <bool translatable="false" name="config_tether_dun_required">false</bool>
+    <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
+    <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
+    <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH -->
+    <integer-array translatable="false" name="config_tether_upstream_types">
+        <item>1</item>
+        <item>4</item>
+    </integer-array>
 
     <!-- String containing the apn value for tethering.  May be overriden by secure settings
          TETHER_DUN_APN.  Value is a comma separated series of strings:
@@ -198,7 +202,7 @@
          the slider is open.  This can be set or unset depending how easily
          the slider can be opened (for example, in a pocket or purse). -->
     <bool name="config_bypass_keyguard_if_slider_open">true</bool>
-    
+
     <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
@@ -208,10 +212,10 @@
 
     <!-- If this is true, the screen will come on when you unplug usb/power/whatever. -->
     <bool name="config_unplugTurnsOnScreen">false</bool>
-    
+
     <!-- If this is true, the screen will fade off. -->
     <bool name="config_animateScreenLights">true</bool>
-    
+
     <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
 
     <!-- If true, the screen can be rotated via the accelerometer in all 4
@@ -296,7 +300,7 @@
         <item>20</item>
         <item>21</item>
     </integer-array>
-    
+
     <!-- Vibrator pattern for feedback about touching a virtual key -->
     <integer-array name="config_virtualKeyVibePattern">
         <item>0</item>
@@ -376,8 +380,8 @@
     <!-- Allow the menu hard key to be disabled in LockScreen on some devices -->
     <bool name="config_disableMenuKeyInLockScreen">false</bool>
 
-    <!-- Show sliding tab before lockscreen -->
-    <bool name="config_enableSlidingTabFirst">true</bool>
+    <!-- Don't show lock screen before unlock screen (PIN/pattern/password) -->
+    <bool name="config_enableLockBeforeUnlockScreen">false</bool>
 
     <!-- Diable lockscreen rotation by default -->
     <bool name="config_enableLockScreenRotation">false</bool>
@@ -456,7 +460,7 @@
          This feature should be disabled for most devices. -->
     <integer name="config_virtualKeyQuietTimeMillis">0</integer>
 
-    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not 
+    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
          specified -->
     <string name="default_wallpaper_component">@null</string>
 
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 20cb852..a5e5f70 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -118,15 +118,19 @@
     <!-- Default height of an action bar. -->
     <dimen name="action_bar_default_height">48dip</dimen>
     <!-- Vertical padding around action bar icons. -->
-    <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
+    <dimen name="action_bar_icon_vertical_padding">8dip</dimen>
+    <!-- Text size for action bar titles -->
+    <dimen name="action_bar_title_text_size">18dp</dimen>
+    <!-- Text size for action bar subtitles -->
+    <dimen name="action_bar_subtitle_text_size">14dp</dimen>
 
-    <!-- Size of clock font in LockScreen. -->
-    <dimen name="keyguard_pattern_unlock_clock_font_size">80sp</dimen>
+    <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
+    <dimen name="keyguard_lockscreen_clock_font_size">80sp</dimen>
 
-    <!-- Size of status line font in LockScreen. -->
-    <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
+    <!-- Size of status line font on Unsecure unlock LockScreen. -->
+    <dimen name="keyguard_lockscreen_status_line_font_size">14sp</dimen>
 
-    <!-- Size of right margin in LockScreen -->
-    <dimen name="keyguard_pattern_unlock_status_line_font_right_margin">20dip</dimen>
+    <!-- Size of right margin on Unsecure unlock LockScreen -->
+    <dimen name="keyguard_lockscreen_status_line_font_right_margin">45dip</dimen>
 
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 580c204..db6f98f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1769,13 +1769,18 @@
   <public type="attr" name="listPreferredItemHeightLarge" />
   <public type="attr" name="listPreferredItemHeightSmall" />
 
+  <public type="attr" name="paddingStart"/>
+  <public type="attr" name="paddingEnd"/>
+  <public type="attr" name="layout_marginStart"/>
+  <public type="attr" name="layout_marginEnd"/>
+
+  <public type="attr" name="actionBarSplitStyle" />
+
   <public type="style" name="Widget.Holo.Button.Borderless.Small" />
   <public type="style" name="Widget.Holo.Light.Button.Borderless.Small" />
 
   <public type="integer" name="status_bar_notification_info_maxnum" />
   <public type="string" name="status_bar_notification_info_overflow" />
 
-  <public type="attr" name="paddingStart"/>
-  <public type="attr" name="paddingEnd"/>
-
+  <public type="attr" name="textDirection"/>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a525ee3..88ed9c6b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2964,4 +2964,26 @@
     <!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
     <string name="data_usage_limit_body">tap to enable</string>
 
+    <!-- SSL Certificate dialogs -->
+    <!-- Title for an SSL Certificate dialog -->
+    <string name="ssl_certificate">Security certificate</string>
+    <!-- Message on an SSL Certificate dialog -->
+    <string name="ssl_certificate_is_valid">This certificate is valid.</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="issued_to">Issued to:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="common_name">Common name:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="org_name">Organization:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="org_unit">Organizational unit:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="issued_by">Issued by:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="validity_period">Validity:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="issued_on">Issued on:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="expires_on">Expires on:</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 72a5797..5244b74 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1118,9 +1118,9 @@
 
     <style name="Widget.ActionButton">
         <item name="android:background">?android:attr/selectableItemBackground</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
-        <item name="android:minWidth">64dip</item>
+        <item name="android:paddingLeft">12dip</item>
+        <item name="android:paddingRight">12dip</item>
+        <item name="android:minWidth">56dip</item>
         <item name="android:minHeight">?android:attr/actionBarSize</item>
     </style>
 
@@ -1296,10 +1296,12 @@
 
     <style name="TextAppearance.Holo.Widget.ActionBar.Title"
            parent="TextAppearance.Holo.Medium">
+        <item name="android:textSize">@android:dimen/action_bar_title_text_size</item>
     </style>
 
     <style name="TextAppearance.Holo.Widget.ActionBar.Subtitle"
            parent="TextAppearance.Holo.Small">
+        <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item>
     </style>
 
     <style name="TextAppearance.Holo.Widget.ActionMode">
@@ -1788,18 +1790,16 @@
     </style>
 
     <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
-        <item name="android:minWidth">64dip</item>
+        <item name="android:minWidth">56dip</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
+        <item name="android:paddingLeft">12dip</item>
+        <item name="android:paddingRight">12dip</item>
         <item name="android:scaleType">center</item>
     </style>
 
     <style name="Widget.Holo.ActionButton.Overflow">
         <item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_dark</item>
         <item name="android:background">?android:attr/selectableItemBackground</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
         <item name="android:contentDescription">@string/action_menu_overflow_description</item>
     </style>
 
@@ -2142,8 +2142,6 @@
 
     <style name="Widget.Holo.Light.ActionButton.Overflow">
         <item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_light</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
         <item name="android:contentDescription">@string/action_menu_overflow_description</item>
     </style>
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 2ab2c04..78e9975 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -280,6 +280,7 @@
         <item name="actionModeStyle">@style/Widget.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.ActionButton.CloseMode</item>
         <item name="actionBarStyle">@android:style/Widget.ActionBar</item>
+        <item name="actionBarSplitStyle">?android:attr/actionBarStyle</item>
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">?android:attr/popupWindowStyle</item>
         <item name="actionMenuTextAppearance">?android:attr/textAppearanceMedium</item>
@@ -693,17 +694,14 @@
 
     <!-- Theme for the search input bar. -->
     <style name="Theme.SearchBar" parent="Theme.Holo.Light.Panel">
-        <item name="windowContentOverlay">@null</item>        
         <item name="actionModeBackground">@android:drawable/cab_background_opaque_holo_light</item>
     </style>
 
     <style name="Theme.Holo.SearchBar" parent="Theme.Holo.Panel">
-        <item name="windowContentOverlay">@null</item>
         <item name="actionModeBackground">@android:drawable/cab_background_opaque_holo_dark</item>
     </style>
 
     <style name="Theme.Holo.Light.SearchBar" parent="Theme.Holo.Light.Panel">
-        <item name="windowContentOverlay">@null</item>
         <item name="actionModeBackground">@android:drawable/cab_background_opaque_holo_light</item>
     </style>
 
diff --git a/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java b/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
index da77298..cf9e6e6 100644
--- a/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
+++ b/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
@@ -28,9 +28,17 @@
 import java.io.StringWriter;
 import junit.framework.TestCase;
 import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.auth.DigestScheme;
 import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicHeader;
 
+/**
+ * Tests for various regressions and problems with DefaultHttpClient. This is
+ * not a comprehensive test!
+ */
 public final class DefaultHttpClientTest extends TestCase {
 
     private MockWebServer server = new MockWebServer();
@@ -87,4 +95,40 @@
         reader.close();
         return writer.toString();
     }
+
+    // http://code.google.com/p/android/issues/detail?id=16051
+    public void testDigestSchemeAlgorithms() throws Exception {
+        authenticateDigestAlgorithm("MD5");
+        authenticateDigestAlgorithm("MD5-sess");
+        authenticateDigestAlgorithm("md5");
+        authenticateDigestAlgorithm("md5-sess");
+        authenticateDigestAlgorithm("md5-SESS");
+        authenticateDigestAlgorithm("MD5-SESS");
+        try {
+            authenticateDigestAlgorithm("MD5-");
+        } catch (AuthenticationException expected) {
+        }
+        try {
+            authenticateDigestAlgorithm("MD6");
+        } catch (AuthenticationException expected) {
+        }
+        try {
+            authenticateDigestAlgorithm("MD");
+        } catch (AuthenticationException expected) {
+        }
+        try {
+            authenticateDigestAlgorithm("");
+        } catch (AuthenticationException expected) {
+        }
+    }
+
+    private void authenticateDigestAlgorithm(String algorithm) throws Exception {
+        String challenge = "Digest realm=\"protected area\", "
+                + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
+                + "algorithm=" + algorithm;
+        DigestScheme digestScheme = new DigestScheme();
+        digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", challenge));
+        HttpGet get = new HttpGet();
+        digestScheme.authenticate(new UsernamePasswordCredentials("username", "password"), get);
+    }
 }
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index aedfbad..2ed7c52 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -95,7 +95,7 @@
     private WebView mWebView;
 
     /** Used for caching the default bindings so they can be restored. */
-    private String mDefaultKeyBindings;
+    private static String sDefaultKeyBindings;
 
     /** The received selection string for assertion checking. */
     private static String sReceivedSelectionString = SELECTION_STRING_UNKNOWN;
@@ -1696,7 +1696,7 @@
      */
     private void injectTestWebContentKeyBindings() {
         ContentResolver contentResolver = getActivity().getContentResolver();
-        mDefaultKeyBindings = Settings.Secure.getString(contentResolver,
+        sDefaultKeyBindings = Settings.Secure.getString(contentResolver,
                 Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS);
         Settings.Secure.putString(contentResolver,
                 Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, TEST_KEY_DINDINGS);
@@ -1708,7 +1708,7 @@
     private void restoreDefaultWebContentKeyBindings() {
         Settings.Secure.putString(getActivity().getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
-                mDefaultKeyBindings);
+                sDefaultKeyBindings);
     }
 
     /**
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index d8d145c..a37f1a3 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -22,6 +22,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.GetChars;
+import android.view.View;
 import android.widget.TextView;
 
 /**
@@ -58,4 +59,122 @@
         assertEquals('o', c2[4]);
         assertEquals('\0', c2[5]);
     }
+
+    @SmallTest
+    public void testTextDirectionDefault() {
+        TextView tv = new TextView(mContext);
+        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+    }
+
+    @SmallTest
+    public void testSetGetTextDirection() {
+        TextView tv = new TextView(mContext);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionLtr() {
+        TextView tv = new TextView(mContext);
+        tv.setText("this is a test");
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionLtrWithInheritance() {
+        LinearLayout ll = new LinearLayout(mContext);
+        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+        TextView tv = new TextView(mContext);
+        tv.setText("this is a test");
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionRtl() {
+        TextView tv = new TextView(mContext);
+        tv.setText("\u05DD\u05DE"); // hebrew
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionRtlWithInheritance() {
+        LinearLayout ll = new LinearLayout(mContext);
+        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+        TextView tv = new TextView(mContext);
+        tv.setText("\u05DD\u05DE"); // hebrew
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
 }
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
new file mode 100644
index 0000000..be2e6bf
--- /dev/null
+++ b/core/tests/notificationtests/Android.mk
@@ -0,0 +1,16 @@
+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_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := NotificationStressTests
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/notificationtests/AndroidManifest.xml b/core/tests/notificationtests/AndroidManifest.xml
new file mode 100644
index 0000000..51e530a
--- /dev/null
+++ b/core/tests/notificationtests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.notification.tests" >
+
+    <application >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.notification.tests"
+        android:label="Notification Stress Tests" />
+
+</manifest>
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
new file mode 100644
index 0000000..52ea1c4
--- /dev/null
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.app;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.test.RepetitiveTest;
+import android.test.TimedTest;
+
+import java.util.Random;
+
+/**
+ * Test which spams notification manager with a large number of notifications, for both stress and
+ * performance testing.
+ */
+public class NotificationStressTest extends InstrumentationTestCase {
+
+    private static final int NUM_ITERATIONS = 200;
+    private static final int[] ICONS = new int[] {
+        android.R.drawable.stat_notify_call_mute,
+        android.R.drawable.stat_notify_chat,
+        android.R.drawable.stat_notify_error,
+        android.R.drawable.stat_notify_missed_call,
+        android.R.drawable.stat_notify_more,
+        android.R.drawable.stat_notify_sdcard,
+        android.R.drawable.stat_notify_sdcard_prepare,
+        android.R.drawable.stat_notify_sdcard_usb,
+        android.R.drawable.stat_notify_sync,
+        android.R.drawable.stat_notify_sync_noanim,
+        android.R.drawable.stat_notify_voicemail,
+    };
+
+    private final Random mRandom = new Random();
+    private Context mContext;
+    private NotificationManager mNotificationManager;
+    private int notifyId = 0;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getContext();
+        mNotificationManager = (NotificationManager) mContext.getSystemService(
+                Context.NOTIFICATION_SERVICE);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mNotificationManager.cancelAll();
+    }
+
+    @RepetitiveTest(numIterations=NUM_ITERATIONS)
+    public void testNotificationStress() {
+        // Cancel one of every five notifications to vary load on notification manager
+        if (notifyId % 5 == 4) {
+            mNotificationManager.cancel(notifyId - 4);
+        }
+        sendNotification(notifyId++, "testNotificationStressNotify");
+    }
+
+    private void sendNotification(int id, CharSequence text) {
+        // Create "typical" notification with random icon
+        Notification notification = new Notification(ICONS[mRandom.nextInt(ICONS.length)], text,
+                System.currentTimeMillis());
+        // Fill in arbitrary content
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
+        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+        CharSequence title = text + " " + id;
+        CharSequence subtitle = String.valueOf(System.currentTimeMillis());
+        notification.setLatestEventInfo(mContext, title, subtitle, pendingIntent);
+        mNotificationManager.notify(id, notification);
+        SystemClock.sleep(10);
+    }
+}
diff --git a/data/fonts/DroidSansEthiopic-Bold.ttf b/data/fonts/DroidSansEthiopic-Bold.ttf
new file mode 100644
index 0000000..e06cac2
--- /dev/null
+++ b/data/fonts/DroidSansEthiopic-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansEthiopic-Regular.ttf b/data/fonts/DroidSansEthiopic-Regular.ttf
new file mode 100644
index 0000000..0adcbbe
--- /dev/null
+++ b/data/fonts/DroidSansEthiopic-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew-Bold.ttf b/data/fonts/DroidSansHebrew-Bold.ttf
new file mode 100644
index 0000000..c1acb38
--- /dev/null
+++ b/data/fonts/DroidSansHebrew-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew-Regular.ttf b/data/fonts/DroidSansHebrew-Regular.ttf
new file mode 100644
index 0000000..af6a58d
--- /dev/null
+++ b/data/fonts/DroidSansHebrew-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew.ttf b/data/fonts/DroidSansHebrew.ttf
deleted file mode 100644
index 8d77e3e..0000000
--- a/data/fonts/DroidSansHebrew.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 692ce34..d222c0b 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -18,7 +18,8 @@
     frameworks/base/data/fonts/DroidSans.ttf:system/fonts/DroidSans.ttf \
     frameworks/base/data/fonts/DroidSans-Bold.ttf:system/fonts/DroidSans-Bold.ttf \
     frameworks/base/data/fonts/DroidSansArabic.ttf:system/fonts/DroidSansArabic.ttf \
-    frameworks/base/data/fonts/DroidSansHebrew.ttf:system/fonts/DroidSansHebrew.ttf \
+    frameworks/base/data/fonts/DroidSansHebrew-Regular.ttf:system/fonts/DroidSansHebrew-Regular.ttf \
+    frameworks/base/data/fonts/DroidSansHebrew-Bold.ttf:system/fonts/DroidSansHebrew-Bold.ttf \
     frameworks/base/data/fonts/DroidSansThai.ttf:system/fonts/DroidSansThai.ttf \
     frameworks/base/data/fonts/DroidSerif-Regular.ttf:system/fonts/DroidSerif-Regular.ttf \
     frameworks/base/data/fonts/DroidSerif-Bold.ttf:system/fonts/DroidSerif-Bold.ttf \
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index 3127e10..cb5a0b6 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -145,6 +145,9 @@
     <td>Kyocera</td>
     <td><code>0482</code></td></tr>
   <tr>
+    <td>Lenevo</td>
+    <td><code>17EF</code></td></tr>
+  <tr>
     <td>LG</td>
     <td><code>1004</code></td></tr>
   <tr>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 55d711f..3ec174e 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -222,7 +222,8 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html">&lt;service&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;</a></li> 
-          <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></li>  <!-- ##api level 4## -->
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a>
+              <span class="new">updated</span></li>  <!-- ##api level 4## -->
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></li> <!-- ##api level 4## -->
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></li>
@@ -256,7 +257,7 @@
 	        <div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
 	            <span class="en">RenderScript</span>
 	          </a>
-	          <span class="new-child">new!</span></div>
+	          <span class="new">new!</span></div>
 	        <ul>
 	          <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
 	                <span class="en">3D Graphics</span>
@@ -270,8 +271,8 @@
   	  </li>
 
       <li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
-            <span class="en">Audio and Video</span>
-          </a></li>
+            <span class="en">Media</span>
+          </a><span class="new">updated</span></li>
       <li>
         <a href="<?cs var:toroot ?>guide/topics/clipboard/copy-paste.html">
             <span class="en">Copy and Paste</span>
@@ -302,11 +303,13 @@
       </li> -->
   <!--<li><a style="color:gray;">Localization</a></li>  -->
       <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
-            <span class="en">App Widgets</span>
-          </a></li>
+            <span class="en">App Widgets</span></a>
+            <span class="new">updated</span>
+          </li>
       <li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
-            <span class="en">Bluetooth</span>
-          </a></li>
+            <span class="en">Bluetooth</span></a>
+            <span class="new">updated</span>
+          </li>
       <li><a href="<?cs var:toroot?>guide/topics/nfc/index.html">
             <span class="en">Near Field Communication</span>
           </a></li>
@@ -337,8 +340,8 @@
           </ul>
       </li>
       <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
-            <span class="en">Device Administration</span>
-         </a>
+            <span class="en">Device Administration</span></a>
+            <span class="new">updated</span>
       </li>
       <li class="toggle-list">
            <div>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index e589292..78b5b51 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -213,7 +213,7 @@
 <p class="note"><strong>Note:</strong> To make your app widget portable across
 devices, your app widget's minimum size should never be larger than 4 x 4 cells.
 See the <a
-href="{@docRoot}guide/practices/ui_guidelines/widget_design.htmll#sizes">App
+href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#sizes">App
 Widget Design Guidelines</a> for more discussion of Home screen cell sizes.</p>
   </li>
   <li>The <code>updatePeriodMillis</code> attribute defines how often the App
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd
index 5cc1b45..cb453da 100644
--- a/docs/html/guide/topics/fundamentals/activities.jd
+++ b/docs/html/guide/topics/fundamentals/activities.jd
@@ -145,7 +145,7 @@
 <h3 id="Declaring">Declaring the activity in the manifest</h3>
 
 <p>You must declare your activity in the manifest file in order for it to
-be accessible to the system. To decalare your activity, open your manifest file and add an <a
+be accessible to the system. To declare your activity, open your manifest file and add an <a
 href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> element
 as a child of the <a
 href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
@@ -163,9 +163,16 @@
 
 <p>There are several other attributes that you can include in this element, to define properties
 such as the label for the activity, an icon for the activity, or a theme to style the activity's
-UI. See the <a
+UI. The <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a>
+attribute is the only required attribute&mdash;it specifies the class name of the activity. Once
+you publish your application, you should not change this name, because if you do, you might break
+some functionality, such as application shortcuts (read the blog post, <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
+That Cannot Change</a>).</p>
+
+<p>See the <a
 href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> element
-reference for more information about available attributes.</p>
+reference for more information about declaring your activity in the manifest.</p>
 
 
 <h4>Using intent filters</h4>
diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd
index 468a417..9c38897 100644
--- a/docs/html/guide/topics/fundamentals/services.jd
+++ b/docs/html/guide/topics/fundamentals/services.jd
@@ -203,7 +203,7 @@
 <p>Like activities (and other components), you must declare all services in your application's
 manifest file.</p>
 
-<p>To decalare your service, add a <a
+<p>To declare your service, add a <a
 href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element
 as a child of the <a
 href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
@@ -222,9 +222,17 @@
 <p>There are other attributes you can include in the <a
 href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element to
 define properties such as permissions required to start the service and the process in
-which the service should run. See the <a
+which the service should run. The <a
+href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
+attribute is the only required attribute&mdash;it specifies the class name of the service. Once
+you publish your application, you should not change this name, because if you do, you might break
+some functionality where explicit intents are used to reference your service (read the blog post, <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
+That Cannot Change</a>).
+
+<p>See the <a
 href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element
-reference for more information.</p>
+reference for more information about declaring your service in the manifest.</p>
 
 <p>Just like an activity, a service can define intent filters that allow other components to
 invoke the service using implicit intents. By declaring intent filters, components
@@ -670,7 +678,7 @@
 either stopped or removed from the foreground.</p>
 
 <p>For example, a music player that plays music from a service should be set to run in the
-foreground, because the user it explicitly aware
+foreground, because the user is explicitly aware
 of its operation. The notification in the status bar might indicate the current song and allow
 the user to launch an activity to interact with the music player.</p>
 
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index c910686..3486212 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -507,6 +507,10 @@
 package name specified in the 
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> 
 element.
+<p>Once you publish your application, you <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">should not
+change this name</a> (unless you've set <code><a
+href="#exported">android:exported</a>="false"</code>).</p>
 
 <p>
 There is no default.  The name must be specified.
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index 598e88f..d737a67 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -47,12 +47,15 @@
 to "{@code http://schemas.android.com/apk/res/android}".</dd>
 
 <dt><a name="package"></a>{@code package}</dt>
-<dd>A full Java package name for the application.  The name should 
+<dd>A full Java-language-style package name for the application.  The name should 
 be unique.  The name may contain uppercase or lowercase letters ('A'
 through 'Z'), numbers, and underscores ('_').  However, individual
-package name parts may only start with letters.  For example, applications
-published by Google could have names in the form
-<code>com.google.app.<i>application_name</i></code>.
+package name parts may only start with letters.
+
+<p>To avoid conflicts with other developers, you should use Internet domain ownership as the
+basis for your package names (in reverse). For example, applications published by Google start with
+<code>com.google</code>. You should also never use the <code>com.example</code> namespace when
+publishing your applications.</p>
 
   <p>
   The package name serves as a unique identifier for the application.
@@ -66,6 +69,12 @@
   element's
   <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">taskAffinity</a></code> attribute).
   </p>
+
+  <p class="caution"><strong>Caution:</strong> Once you publish your application, you
+<strong>cannot change the package name</strong>. The package name defines your application's
+identity, so if you change it, then it is considered to be a different application and users of
+the previous version cannot update to the new version.</p>
+
 </dd>
 
 <dt><a name="uid"></a>{@code android:sharedUserId}</dt>
diff --git a/docs/html/guide/topics/manifest/receiver-element.jd b/docs/html/guide/topics/manifest/receiver-element.jd
index 7012c0f..8416c0c 100644
--- a/docs/html/guide/topics/manifest/receiver-element.jd
+++ b/docs/html/guide/topics/manifest/receiver-element.jd
@@ -122,6 +122,11 @@
 "{@code . ReportReceiver}"), it is appended to the package name specified in 
 the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.  
 
+<p>Once you publish your application, you <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">should not
+change this name</a> (unless you've set <code><a
+href="#exported">android:exported</a>="false"</code>).</p>
+
 <p>
 There is no default.  The name must be specified.
 </p></dd>
diff --git a/docs/html/guide/topics/manifest/service-element.jd b/docs/html/guide/topics/manifest/service-element.jd
index d9a81b3..82d1f6a 100644
--- a/docs/html/guide/topics/manifest/service-element.jd
+++ b/docs/html/guide/topics/manifest/service-element.jd
@@ -6,7 +6,7 @@
 <dl class="xml">
 <dt>syntax:</dt>
 <dd><pre class="stx">&lt;service android:<a href="#enabled">enabled</a>=["true" | "false"]
-         android:<a href="#exported">exported[</a>="true" | "false"]
+         android:<a href="#exported">exported</a>=["true" | "false"]
          android:<a href="#icon">icon</a>="<i>drawable resource</i>"
          android:<a href="#label">label</a>="<i>string resource</i>"
          android:<a href="#nm">name</a>="<i>string</i>"
@@ -121,6 +121,11 @@
 it is appended to the package name specified in the 
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.  
 
+<p>Once you publish your application, you <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">should not
+change this name</a> (unless you've set <code><a
+href="#exported">android:exported</a>="false"</code>).</p>
+
 <p>
 There is no default.  The name must be specified.
 </p></dd>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index ee99a37..605a2bb 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -8,12 +8,15 @@
 <dt>syntax:</dt>
 <dd>
 <pre class="stx">
-&lt;supports-screens android:<a href="#resizeable">resizeable</a>=["true" | "false"]
-                  android:<a href="#small">smallScreens</a>=["true" | "false"] 
-                  android:<a href="#normal">normalScreens</a>=["true" | "false"] 
-                  android:<a href="#large">largeScreens</a>=["true" | "false"] 
+&lt;supports-screens android:<a href="#requiresSmallest">requiresSmallestWidthDp</a>="<em>integer</em>"
+                  android:<a href="#compatibleWidth">compatibleWidthLimitDp</a>="<em>integer</em>"
+                  android:<a href="#largestWidth">largestWidthLimitDp</a>="<em>integer</em>"
+                  android:<a href="#resizeable">resizeable</a>=["true"| "false"]
+                  android:<a href="#small">smallScreens</a>=["true" | "false"]
+                  android:<a href="#normal">normalScreens</a>=["true" | "false"]
+                  android:<a href="#large">largeScreens</a>=["true" | "false"]
                   android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
-                  android:<a href="#any">anyDensity</a>=["true" | "false"] /&gt;
+                  android:<a href="#any">anyDensity</a>=["true" | "false"]  /&gt;
 </pre>
 </dd>
 
@@ -21,36 +24,37 @@
 <dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
 
 <dt>description:</dt>
-<dd>Lets you specify the screen dimensions the
-application supports.  By default, a modern application (using API Level 4 or higher) supports all
-screen sizes; older applications are assumed to support only the "normal" screen size. Screen
-size is determined as the available pixels to an application after density scaling has been
-applied. (Note that screen size is a separate axis from screen density.)
+<dd>Lets you specify the screen sizes your application supports and enable screen
+compatibility mode for screens larger than what your application supports. By default, a modern
+application (using API Level 4 or higher) supports all screen sizes; older applications are assumed
+to support only the "normal" screen size. Screen size is determined by the number of pixels on the
+screen after the system accounts for screen density scaling.
 
-<p>An application "supports" a given screen size if it fills the entire screen and works as
-expected. By default, the system will resize your application to fill the screen, if you have set
+<p>An application "supports" a given screen size if it resizes properly to fill the entire screen.
+By default, the system resizes your application UI to fill the screen if you have set
 either <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
 minSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-targetSdkVersion}</a> to {@code "4"} or higher. Resizing works well for most applications and
-you don't have to do any extra work to make your application work on larger screens.</p>
+targetSdkVersion}</a> to {@code "4"} or higher. Normal resizing works well for most applications and
+you don't have to do any extra work to make your application work on screens larger than a
+handset device.</p>
 
-<p>In addition to allowing the system to resize your application, you can add additional support
-for different screen sizes by providing <a
+<p>In addition to allowing the system to resize your application to fit the current screen, you can
+optimize your UI for different screen sizes by providing <a
 href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
 layout resources</a> for different sizes. For instance, you might want to modify the layout
 of an activity when it is on a tablet or similar device that has an <em>xlarge</em> screen.</p>
 
-<p>If your application does not support <em>large</em> or <em>xlarge</em> screens, then you should
-declare that it is not resizeable by setting <a href="#resizeable">{@code android:resizeable}</a> to
-{@code "false"}, so that the system will not resize your application on larger screens.</p>
+<p>However, if your application does not work well when resized to fit different screen sizes,
+you can use the attributes of the {@code &lt;supports-screens&gt;} element to control whether
+your application should be distributed to smaller screens or have its UI scaled up to fit larger
+screens using the system's screen compatibility mode. When you have not designed for larger screen
+sizes and the normal resizing does not achieve the appropriate results, <em>screen compatibility
+mode</em> will scale your UI by emulating a <em>normal</em> size screen and then zooming in on it so
+that it fills the entire screen&mdash;thus achieving the same layout as a normal handset device on
+the large screen (but this usually causes pixelation and blurring of your UI).</p>
 
-<p>If your application does not support <em>small</em> screens, then
-there isn't much the system can do to make the application work well on a smaller screen, so
-external services (such as Android Market) should not allow users to install the application on such
-screens.</p>
-
-
-<p>For more information, see 
+<p>For more information about how to properly support different screen sizes so that you can avoid
+using screen compatibility mode, read
 <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
 
 
@@ -59,6 +63,74 @@
 <dd>
 <dl class="attr">
   
+  <dt id="requiresSmallest">{@code android:requiresSmallestWidthDp}</dt>
+  <dd>This attribute specifies the minimum "smallest screen width" with which your
+application is compatible. In order for a device to be considered compatible with your
+application, the shortest side of the available screen space must be equal to or greater than this
+value.
+<p>The width against which your value is compared takes into account screen decorations and system
+UI. For example, if the device has some persistent UI elements on the left or right edge of the
+display, the system declares the device's available width as one that is smaller than the actual
+screen size, accounting for these UI elements because those are screen pixels not available for your
+UI. Thus, the value you use should be the actual smallest width required by your layout.</p>
+<p>If your application properly resizes for smaller screen sizes (down to the
+<em>small</em> size or a minimum width of 320dp), you do
+not need to use this attribute. Otherwise, you should use a value for this attribute that
+matches the smallest value used by your application for the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+smallest screen width qualifier</a> ({@code sw&lt;N&gt;dp}).</p>
+
+<p>For example, a typical handset screen has a minimum width of 320dp, a 7" tablet has a minimum
+width of 600dp, and a 10" tablet has a minimum width of 720dp. If the smallest available screen
+width on a device is less than the value you supply here, then the application is considered
+incompatible with that
+device. External services such as Android Market use this to determine whether a device
+is compatible with your application and prevent incompatible devices from installing it.</p>
+<p>Beginning with Android 3.2 (API level 13), using this attribute is the preferred way to
+specify the minimum screen size your application requires, instead of using the other attributes
+for small, normal, large, and xlarge screens. The advantage of using this attribute is that you
+have more control over exactly how much screen space your application needs at a minimum in order
+to properly display its UI, rather than relying on the generalized size groups.</p>
+<p>This attribute has no default value. If this attribute is not specified, then any of the old
+<code><a href="#small">smallScreens</a></code>, <code><a href="#normal">normalScreens</a></code>,
+<code><a href="#large">largeScreens</a></code>, or <code><a href="#xlarge">xlargeScreens</a></code>
+attributes are used instead to determine the smallest screen required.</p>
+     <p>This attribute was introduced in API level 13.</p>
+  </dd>
+
+  <dt id="compatibleWidth">{@code android:compatibleWidthLimitDp}</dt>
+  <dd>This attribute allows you to enable screen compatibility mode as a user-optional feature by
+specifying the maximum "smallest screen width" for which your application is designed. If the value
+you supply here is less than the shortest side of the available screen space, users can still
+install your application, but are offered to run it in screen compatibility mode. By default, screen
+compatibility mode is disabled and your layout is resized to fit the screen as usual, but a
+button is available in the system bar that allows the user to toggle screen compatibility mode on
+and off.
+  <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute.</p>
+  <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:compatibleWidthLimitDp} is larger than 320.</p>
+     <p>This attribute was introduced in API level 13.</p>
+  </dd>
+
+  <dt id="largestWidth">{@code android:largestWidthLimitDp}</dt>
+  <dd>This attribute allows you to force enable screen compatibility mode by specifying the maximum
+"smallest screen width" for which your application is designed. If the value you supply here is less
+than the shortest side of the available screen space, the application runs in screen
+compatibility mode with no way for the user to disable it.
+  <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute. Otherwise, you should first consider using the <a
+href="#compatibleWidth">{@code android:compatibleWidthLimitDp}</a> attribute. You should use the
+{@code android:largestWidthLimitDp} attribute only when your application is functionally broken when
+resized for larger screens and screen compatibility mode is the only way that users should use
+your application.</p>
+  <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:largestWidthLimitDp} is larger than 320.</p>
+     <p>This attribute was introduced in API level 13.</p>
+  </dd>
+
   <dt><a name="resizeable"></a>{@code android:resizeable}</dt>
   <dd>Indicates whether the application is resizeable for different screen sizes. This attribute is
 true, by default, if you have set either <a
@@ -75,6 +147,7 @@
 application does not work well on larger screens, follow the guide to <a
 href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to enable
 additional screen support.</p>
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   
@@ -91,6 +164,7 @@
 {@code "4"} or higher,
 the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
 {@code "false"}.
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   <dt><a name="normal"></a>{@code android:normalScreens}</dt>
@@ -99,12 +173,13 @@
      screen, but WQVGA low density and WVGA high density are also
      considered to be normal.  This attribute is "true" by default,
      and applications currently should leave it that way.
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   <dt><a name="large"></a>{@code android:largeScreens}</dt>
   <dd>Indicates whether the application supports larger screen form-factors.
      A large screen is defined as a screen that is significantly larger
-     than a "normal" phone screen, and thus might require some special care
+     than a "normal" handset screen, and thus might require some special care
      on the application's part to make good use of it, though it may rely on resizing by the
 system to fill the screen. If the application has set either <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
@@ -112,6 +187,7 @@
 {@code "4"} or higher,
 the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
 {@code "false"}.
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
 
   <dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
@@ -125,7 +201,8 @@
 {@code "4"} or higher,
 the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
 {@code "false"}.
-     <p>This attribute was introduced in API Level 9.</p>
+     <p>This attribute was introduced in API level 9.</p>
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   <dt><a name="any"></a>{@code android:anyDensity}</dt>
@@ -142,6 +219,7 @@
 down application assets by a factor of 0.75 (low dpi screens) or scale them up by a factor of 1.5
 (high dpi screens), when you don't provide alternative resources for a specifc screen density. The
 screen density is expressed as dots-per-inch (dpi).</p>
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
 
diff --git a/docs/html/guide/topics/media/images/notification1.png b/docs/html/guide/topics/media/images/notification1.png
new file mode 100644
index 0000000..9b01971
--- /dev/null
+++ b/docs/html/guide/topics/media/images/notification1.png
Binary files differ
diff --git a/docs/html/guide/topics/media/images/notification2.png b/docs/html/guide/topics/media/images/notification2.png
new file mode 100644
index 0000000..488648e
--- /dev/null
+++ b/docs/html/guide/topics/media/images/notification2.png
Binary files differ
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index b6d1629..06e6208 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -1,4 +1,4 @@
-page.title=Audio and Video
+page.title=Media
 @jd:body
 
     <div id="qv-wrapper">
@@ -6,30 +6,44 @@
 
 <h2>Quickview</h2>
 <ul>
-<li>Audio playback and record</li>
-<li>Video playback</li>
-<li>Handles data from raw resources, files, streams</li>
-<li>Built-in codecs for a variety of media. See <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
+<li>MediaPlayer APIs allow you to play and record media</li>
+<li>You can handle data from raw resources, files, and streams</li>
+<li>The platform supports a variety of media formats. See <a
+href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
 </ul>
 
 <h2>In this document</h2>
 <ol>
-<li><a href="#playback">Audio and Video Playback</a>
-    <ol>
-      <li><a href="#playraw">Playing from a Raw Resource</li>
-      <li><a href="#playfile">Playing from a File or Stream</li>
-      <li><a href="#jet">Playing JET Content</li>
-    </ol>
+<li><a href="#mediaplayer">Using MediaPlayer</a>
+   <ol>
+      <li><a href='#preparingasync'>Asynchronous Preparation</a></li>
+      <li><a href='#managestate'>Managing State</a></li>
+      <li><a href='#releaseplayer'>Releasing the MediaPlayer</a></li>
+   </ol>
 </li>
-<li><a href="#capture">Audio Capture</a></li>
+<li><a href="#mpandservices">Using a Service with MediaPlayer</a>
+   <ol>
+      <li><a href="#asyncprepare">Running asynchronously</a></li>
+      <li><a href="#asyncerror">Handling asynchronous errors</a></li>
+      <li><a href="#wakelocks">Using wake locks</a></li>
+      <li><a href="#foregroundserv">Running as a foreground service</a></li>
+      <li><a href="#audiofocus">Handling audio focus</a></li>
+      <li><a href="#cleanup">Performing cleanup</a></li>
+   </ol>
+</li>
+<li><a href="#noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</a>
+<li><a href="#viacontentresolver">Retrieving Media from a Content Resolver</a>
+<li><a href="#jetcontent">Playing JET content</a>
+<li><a href="#audiocapture">Performing Audio Capture</a>
 </ol>
 
 <h2>Key classes</h2>
 <ol>
-<li>{@link android.media.MediaPlayer MediaPlayer}</li>
-<li>{@link android.media.MediaRecorder MediaRecorder}</li>
-<li>{@link android.media.JetPlayer JetPlayer}</li>
-<li>{@link android.media.SoundPool SoundPool}</li>
+<li>{@link android.media.MediaPlayer}</li>
+<li>{@link android.media.MediaRecorder}</li>
+<li>{@link android.media.AudioManager}</li>
+<li>{@link android.media.JetPlayer}</li>
+<li>{@link android.media.SoundPool}</li>
 </ol>
 
 <h2>See also</h2>
@@ -41,129 +55,729 @@
 </div>
 </div>
 
-<p>The Android platform offers built-in encoding/decoding for a variety of
-common media types, so that you can easily integrate audio, video, and images into your
-applications. Accessing the platform's media capabilities is fairly straightforward 
-&mdash; you do so using the same intents and activities mechanism that the rest of
-Android uses.</p>
+<p>The Android multimedia framework includes support for encoding and decoding a
+variety of common media types, so that you can easily integrate audio,
+video and images into your applications. You can play audio or video from media files stored in your 
+application's resources (raw resources), from standalone files in the filesystem, or from a data
+stream arriving over a network connection, all using {@link android.media.MediaPlayer} APIs.</p>
 
-<p>Android lets you play audio and video from several types of data sources. You
-can play audio or video from media files stored in the application's resources
-(raw resources), from standalone files in the filesystem, or from a data stream
-arriving over a network connection. To play audio or video from your
-application, use the {@link android.media.MediaPlayer} class.</p>
+<p>You can also record audio and video using the {@link android.media.MediaRecorder} APIs if
+supported by the device hardware. Note that the emulator doesn't have hardware to capture audio or
+video, but actual mobile devices are likely to provide these capabilities.</p>
 
-<p>The platform also lets you record audio and video, where supported by the
-mobile device hardware. To record audio or video, use the {@link
-android.media.MediaRecorder} class. Note that the emulator doesn't have hardware
-to capture audio or video, but actual mobile devices are likely to provide these
-capabilities, accessible through the MediaRecorder class. </p>
+<p>This document shows you how to write a media-playing application that interacts with the user and
+the system in order to obtain good performance and a pleasant user experience.</p>
 
-<p>For a list of media formats for which Android offers built-in support,
-see the <a href="{@docRoot}guide/appendix/media-formats.html">Android Media
-Formats</a> appendix. </p>
+<p class="note"><strong>Note:</strong> You can play back the audio data only to the standard output
+device. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound
+files in the conversation audio during a call.</p>
 
-<h2 id="playback">Audio and Video Playback</h2>
-<p>Media can be played from anywhere: from a raw resource, from a file from the system, 
-or from an available network (URL).</p>
-  
-<p>You can play back the audio data only to the standard
-output device; currently, that is the mobile device speaker or Bluetooth headset. You
-cannot play sound files in the conversation audio. </p>
 
-<h3 id="playraw">Playing from a Raw Resource</h3>
-<p>Perhaps the most common thing to want to do is play back media (notably sound)
-within your own applications. Doing this is easy:</p>
-<ol>
-  <li>Put the sound (or other media resource) file into the <code>res/raw</code>
-  folder of your project, where the Eclipse plugin (or aapt) will find it and
-  make it into a resource that can be referenced from your R class</li>
-  <li>Create an instance of <code>MediaPlayer</code>, referencing that resource using
-  {@link android.media.MediaPlayer#create MediaPlayer.create}, and then call
-  {@link android.media.MediaPlayer#start() start()} on the instance:</li>
-</ol>
-<pre>
-    MediaPlayer mp = MediaPlayer.create(context, R.raw.sound_file_1);
-    mp.start();
+<h2 id="mediaplayer">Using MediaPlayer</h2>
+
+<p>One of the most important components of the media framework is the
+{@link android.media.MediaPlayer MediaPlayer}
+class. An object of this class can fetch, decode, and play both audio and video
+with minimal setup. It supports several different media sources such as:
+<ul>
+   <li>Local resources</li>
+   <li>Internal URIs, such as one you might obtain from a Content Resolver</li>
+   <li>External URLs (streaming)</li>
+</ul>
+</p>
+
+<p>For a list of media formats that Android supports,
+see the <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media
+Formats</a> document. </p>
+
+<p>Here is an example
+of how to play audio that's available as a local raw resource (saved in your application's
+{@code res/raw/} directory):</p>
+
+<pre>MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
+mediaPlayer.start(); // no need to call prepare(); create() does that for you
 </pre>
-<p>To stop playback, call {@link android.media.MediaPlayer#stop() stop()}. If 
-you wish to later replay the media, then you must 
-{@link android.media.MediaPlayer#reset() reset()} and
-{@link android.media.MediaPlayer#prepare() prepare()} the MediaPlayer object
-before calling {@link android.media.MediaPlayer#start() start()} again. 
-(<code>create()</code> calls <code>prepare()</code> the first time.)</p>
-<p>To pause playback, call {@link android.media.MediaPlayer#pause() pause()}. 
-Resume playback from where you paused with 
-{@link android.media.MediaPlayer#start() start()}.</p>
 
-<h3 id="playfile">Playing from a File or Stream</h3>
-<p>You can play back media files from the filesystem or a web URL:</p>
-<ol>
-  <li>Create an instance of the <code>MediaPlayer</code> using <code>new</code></li>
-  <li>Call {@link android.media.MediaPlayer#setDataSource setDataSource()}
-    with a String containing the path (local filesystem or URL)
-    to the file you want to play</li>
-  <li>First {@link android.media.MediaPlayer#prepare prepare()} then
-  {@link android.media.MediaPlayer#start() start()} on the instance:</li>
-</ol>
-<pre>
-    MediaPlayer mp = new MediaPlayer();
-    mp.setDataSource(PATH_TO_FILE);
-    mp.prepare();
-    mp.start();
-</pre>
-<p>{@link android.media.MediaPlayer#stop() stop()} and 
-{@link android.media.MediaPlayer#pause() pause()} work the same as discussed
-above.</p>
-  <p class="note"><strong>Note:</strong>
-  <code>IllegalArgumentException</code> and <code>IOException</code> either
-  need to be caught or passed on when using <code>setDataSource()</code>, since
-  the file you are referencing may not exist.</p>
+<p>In this case, a "raw" resource is a file that the system does not
+try to parse in any particular way. However, the content of this resource should not
+be raw audio. It should be a properly encoded and formatted media file in one 
+of the supported formats.</p>
+
+<p>And here is how you might play from a URI available locally in the system
+(that you obtained through a Content Resolver, for instance):</p>
+
+<pre>Uri myUri = ....; // initialize Uri here
+MediaPlayer mediaPlayer = new MediaPlayer();
+mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+mediaPlayer.setDataSource(getApplicationContext(), myUri);
+mediaPlayer.prepare();
+mediaPlayer.start();</pre>
+
+<p>Playing from a remote URL via HTTP streaming looks like this:</p>
+
+<pre>String url = "http://........"; // your URL here
+MediaPlayer mediaPlayer = new MediaPlayer();
+mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+mediaPlayer.setDataSource(url);
+mediaPlayer.prepare(); // might take long! (for buffering, etc)
+mediaPlayer.start();</pre>
+
 <p class="note"><strong>Note:</strong>
-If you're passing a URL to an online media file, the file must be capable of 
+If you're passing a URL to stream an online media file, the file must be capable of
 progressive download.</p>
 
-<h3 id="jet">Playing JET content</h3>
-<p>The Android platform includes a JET engine that lets you add interactive playback of JET audio content in your applications. You can create JET content for interactive playback using the JetCreator authoring application that ships with the SDK. To play and manage JET content from your application, use the {@link android.media.JetPlayer JetPlayer} class.</p>
+<p class="caution"><strong>Caution:</strong> You must either catch or pass
+{@link java.lang.IllegalArgumentException} and {@link java.io.IOException} when using
+{@link android.media.MediaPlayer#setDataSource setDataSource()}, because
+the file you are referencing might not exist.</p>
 
-<p>For a description of JET concepts and instructions on how to use the JetCreator authoring tool, see the <a href="{@docRoot}guide/topics/media/jet/jetcreator_manual.html">JetCreator User Manual</a>. The tool is available fully-featured on the OS X and Windows platforms and the Linux version supports all the content creation features, but not the auditioning of the imported assets. </p>
+<h3 id='#preparingasync'>Asynchronous Preparation</h3>
 
-<p>Here's an example of how to set up JET playback from a .jet file stored on the SD card:</p>
+<p>Using {@link android.media.MediaPlayer MediaPlayer} can be straightforward in
+principle. However, it's important to keep in mind that a few more things are
+necessary to integrate it correctly with a typical Android application. For
+example, the call to {@link android.media.MediaPlayer#prepare prepare()} can
+take a long time to execute, because
+it might involve fetching and decoding media data. So, as is the case with any
+method that may take long to execute, you should <strong>never call it from your
+application's UI thread</strong>. Doing that will cause the UI to hang until the method returns,
+which is a very bad user experience and can cause an ANR (Application Not Responding) error. Even if
+you expect your resource to load quickly, remember that anything that takes more than a tenth
+of a second to respond in the UI will cause a noticeable pause and will give
+the user the impression that your application is slow.</p>
+
+<p>To avoid hanging your UI thread, spawn another thread to
+prepare the {@link android.media.MediaPlayer} and notify the main thread when done. However, while
+you could write the threading logic
+yourself, this pattern is so common when using {@link android.media.MediaPlayer} that the framework
+supplies a convenient way to accomplish this task by using the
+{@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. This method
+starts preparing the media in the background and returns immediately. When the media
+is done preparing, the {@link android.media.MediaPlayer.OnPreparedListener#onPrepared onPrepared()}
+method of the {@link android.media.MediaPlayer.OnPreparedListener
+MediaPlayer.OnPreparedListener}, configured through
+{@link android.media.MediaPlayer#setOnPreparedListener setOnPreparedListener()} is called.</p>
+
+<h3 id='#managestate'>Managing State</h3>
+
+<p>Another aspect of a {@link android.media.MediaPlayer} that you should keep in mind is
+that it's state-based. That is, the {@link android.media.MediaPlayer} has an internal state
+that you must always be aware of when writing your code, because certain operations
+are only valid when then player is in specific states. If you perform an operation while in the
+wrong state, the system may throw an exception or cause other undesireable behaviors.</p>
+
+<p>The documentation in the
+{@link android.media.MediaPlayer MediaPlayer} class shows a complete state diagram,
+that clarifies which methods move the {@link android.media.MediaPlayer} from one state to another.
+For example, when you create a new {@link android.media.MediaPlayer}, it is in the <em>Idle</em>
+state. At that point, you should initialize it by calling
+{@link android.media.MediaPlayer#setDataSource setDataSource()}, bringing it
+to the <em>Initialized</em> state. After that, you have to prepare it using either the
+{@link android.media.MediaPlayer#prepare prepare()} or
+{@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. When
+the {@link android.media.MediaPlayer} is done preparing, it will then enter the <em>Prepared</em>
+state, which means you can call {@link android.media.MediaPlayer#start start()}
+to make it play the media. At that point, as the diagram illustrates,
+you can move between the <em>Started</em>, <em>Paused</em> and <em>PlaybackCompleted</em> states by
+calling such methods as
+{@link android.media.MediaPlayer#start start()},
+{@link android.media.MediaPlayer#pause pause()}, and
+{@link android.media.MediaPlayer#seekTo seekTo()},
+amongst others. When you
+call {@link android.media.MediaPlayer#stop stop()}, however, notice that you
+cannot call {@link android.media.MediaPlayer#start start()} again until you
+prepare the {@link android.media.MediaPlayer} again.</p>
+
+<p>Always keep <a href='{@docRoot}images/mediaplayer_state_diagram.gif'>the state diagram</a> 
+in mind when writing code that interacts with a
+{@link android.media.MediaPlayer} object, because calling its methods from the wrong state is a
+common cause of bugs.</p>
+
+<h3 id='#releaseplayer'>Releasing the MediaPlayer</h3>
+
+<p>A {@link android.media.MediaPlayer MediaPlayer} can consume valuable
+system resources.
+Therefore, you should always take extra precautions to make sure you are not
+hanging on to a {@link android.media.MediaPlayer} instance longer than necessary. When you
+are done with it, you should always call
+{@link android.media.MediaPlayer#release release()} to make sure any
+system resources allocated to it are properly released. For example, if you are
+using a {@link android.media.MediaPlayer} and your activity receives a call to {@link
+android.app.Activity#onStop onStop()}, you must release the {@link android.media.MediaPlayer},
+because it
+makes little sense to hold on to it while your activity is not interacting with
+the user (unless you are playing media in the background, which is discussed in the next section).
+When your activity is resumed or restarted, of course, you need to
+create a new {@link android.media.MediaPlayer} and prepare it again before resuming playback.</p>
+
+<p>Here's how you should release and then nullify your {@link android.media.MediaPlayer}:</p>
+<pre>
+mediaPlayer.release();
+mediaPlayer = null;
+</pre>
+
+<p>As an example, consider the problems that could happen if you
+forgot to release the {@link android.media.MediaPlayer} when your activity is stopped, but create a
+new one when the activity starts again. As you may know, when the user changes the
+screen orientation (or changes the device configuration in another way), 
+the system handles that by restarting the activity (by default), so you might quickly
+consume all of the system resources as the user
+rotates the device back and forth between portrait and landscape, because at each
+orientation change, you create a new {@link android.media.MediaPlayer} that you never
+release. (For more information about runtime restarts, see <a
+href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a>.)</p>
+
+<p>You may be wondering what happens if you want to continue playing
+"background media" even when the user leaves your activity, much in the same
+way that the built-in Music application behaves. In this case, what you need is
+a {@link android.media.MediaPlayer MediaPlayer} controlled by a {@link android.app.Service}, as
+discussed in <a href="mpandservices">Using a Service with MediaPlayer</a>.</p>
+
+<h2 id="mpandservices">Using a Service with MediaPlayer</h2>
+
+<p>If you want your media to play in the background even when your application
+is not onscreen&mdash;that is, you want it to continue playing while the user is
+interacting with other applications&mdash;then you must start a
+{@link android.app.Service Service} and control the
+{@link android.media.MediaPlayer MediaPlayer} instance from there.
+You should be careful about this setup, because the user and the system have expectations
+about how an application running a background service should interact with the rest of the
+system. If your application does not fulfil those expectations, the user may
+have a bad experience. This section describes the main issues that you should be
+aware of and offers suggestions about how to approach them.</p>
+
+
+<h3 id="asyncprepare">Running asynchronously</h3>
+
+<p>First of all, like an {@link android.app.Activity Activity}, all work in a
+{@link android.app.Service Service} is done in a single thread by
+default&mdash;in fact, if you're running an activity and a service from the same application, they
+use the same thread (the "main thread") by default. Therefore, services need to
+process incoming intents quickly
+and never perform lengthy computations when responding to them. If any heavy
+work or blocking calls are expected, you must do those tasks asynchronously: either from
+another thread you implement yourself, or using the framework's many facilities
+for asynchronous processing.</p>
+
+<p>For instance, when using a {@link android.media.MediaPlayer} from your main thread,
+you should call {@link android.media.MediaPlayer#prepareAsync prepareAsync()} rather than
+{@link android.media.MediaPlayer#prepare prepare()}, and implement
+a {@link android.media.MediaPlayer.OnPreparedListener MediaPlayer.OnPreparedListener}
+in order to be notified when the preparation is complete and you can start playing.
+For example:</p>
 
 <pre>
-JetPlayer myJet = JetPlayer.getJetPlayer();
-myJet.loadJetFile("/sdcard/level1.jet");
+public class MyService extends Service implements MediaPlayer.OnPreparedListener {
+    private static final ACTION_PLAY = "com.example.action.PLAY";
+    MediaPlayer mMediaPlayer = null;
+
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        ...
+        if (intent.getAction().equals(ACTION_PLAY)) {
+            mMediaPlayer = ... // initialize it here
+            mMediaPlayer.setOnPreparedListener(this);
+            mMediaPlayer.prepareAsync(); // prepare async to not block main thread
+        }
+    }
+
+    /** Called when MediaPlayer is ready */
+    public void onPrepared(MediaPlayer player) {
+        player.start();
+    }
+}
+</pre>
+
+
+<h3 id="asyncerror">Handling asynchronous errors</h3>
+
+<p>On synchronous operations, errors would normally
+be signaled with an exception or an error code, but whenever you use asynchronous
+resources, you should make sure your application is notified
+of errors appropriately. In the case of a {@link android.media.MediaPlayer MediaPlayer},
+you can accomplish this by implementing a
+{@link android.media.MediaPlayer.OnErrorListener MediaPlayer.OnErrorListener} and
+setting it in your {@link android.media.MediaPlayer} instance:</p>
+
+<pre>
+public class MyService extends Service implements MediaPlayer.OnErrorListener {
+    MediaPlayer mMediaPlayer;
+
+    public void initMediaPlayer() {
+        // ...initialize the MediaPlayer here...
+
+        mMediaPlayer.setOnErrorListener(this);
+    }
+
+    &#64;Override
+    public boolean onError(MediaPlayer mp, int what, int extra) {
+        // ... react appropriately ...
+        // The MediaPlayer has moved to the Error state, must be reset!
+    }
+}
+</pre>
+
+<p>It's important to remember that when an error occurs, the {@link android.media.MediaPlayer}
+moves to the <em>Error</em> state (see the documentation for the
+{@link android.media.MediaPlayer MediaPlayer} class for the full state diagram)
+and you must reset it before you can use it again.
+
+
+<h3 id="wakelocks">Using wake locks</h3>
+
+<p>When designing applications that play media
+in the background, the device may go to sleep
+while your service is running. Because the Android system tries to conserve
+battery while the device is sleeping, the system tries to shut off any 
+of the phone's features that are
+not necessary, including the CPU and the WiFi hardware.
+However, if your service is playing or streaming music, you want to prevent
+the system from interfering with your playback.</p>
+
+<p>In order to ensure that your service continues to run under
+those conditions, you have to use "wake locks." A wake lock is a way to signal to
+the system that your application is using some feature that should
+stay available even if the phone is idle.</p>
+
+<p class="caution"><strong>Notice:</strong> You should always use wake locks sparingly and hold them
+only for as long as truly necessary, because they significantly reduce the battery life of the
+device.</p>
+
+<p>To ensure that the CPU continues running while your {@link android.media.MediaPlayer} is
+playing, call the {@link android.media.MediaPlayer#setWakeMode
+setWakeMode()} method when initializing your {@link android.media.MediaPlayer}. Once you do,
+the {@link android.media.MediaPlayer} holds the specified lock while playing and releases the lock
+when paused or stopped:</p>
+
+<pre>
+mMediaPlayer = new MediaPlayer();
+// ... other initialization here ...
+mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
+</pre>
+
+<p>However, the wake lock acquired in this example guarantees only that the CPU remains awake. If
+you are streaming media over the
+network and you are using Wi-Fi, you probably want to hold a
+{@link android.net.wifi.WifiManager.WifiLock WifiLock} as
+well, which you must acquire and release manually. So, when you start preparing the
+{@link android.media.MediaPlayer} with the remote URL, you should create and acquire the Wi-Fi lock.
+For example:</p>
+
+<pre>
+WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
+    .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
+
+wifiLock.acquire();
+</pre>
+
+<p>When you pause or stop your media, or when you no longer need the
+network, you should release the lock:</p>
+
+<pre>
+wifiLock.release();
+</pre>
+
+
+<h3 id="foregroundserv">Running as a foreground service</h3>
+
+<p>Services are often used for performing background tasks, such as fetching emails,
+synchronizing data, downloading content, amongst other possibilities. In these
+cases, the user is not actively aware of the service's execution, and probably
+wouldn't even notice if some of these services were interrupted and later restarted.</p>
+
+<p>But consider the case of a service that is playing music. Clearly this is a service that the user
+is actively aware of and the experience would be severely affected by any interruptions.
+Additionally, it's a service that the user will likely wish to interact with during its execution.
+In this case, the service should run as a "foreground service." A
+foreground service holds a higher level of importance within the system&mdash;the system will
+almost never kill the service, because it is of immediate importance to the user. When running
+in the foreground, the service also must provide a status bar notification to ensure that users are
+aware of the running service and allow them to open an activity that can interact with the
+service.</p>
+
+<p>In order to turn your service into a foreground service, you must create a
+{@link android.app.Notification Notification} for the status bar and call
+{@link android.app.Service#startForeground startForeground()} from the {@link
+android.app.Service}. For example:</p>
+
+<pre>String songName;
+// assign the song name to songName
+PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
+                new Intent(getApplicationContext(), MainActivity.class),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+Notification notification = new Notification();
+notification.tickerText = text;
+notification.icon = R.drawable.play0;
+notification.flags |= Notification.FLAG_ONGOING_EVENT;
+notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
+                "Playing: " + songName, pi);
+startForeground(NOTIFICATION_ID, notification);
+</pre>
+
+<p>While your service is running in the foreground, the notification you
+configured is visible in the notification area of the device. If the user
+selects the notification, the system invokes the {@link android.app.PendingIntent} you supplied. In
+the example above, it opens an activity ({@code MainActivity}).</p>
+
+<p>Figure 1 shows how your notification appears to the user:</p>
+
+<img src='images/notification1.png' />
+&nbsp;&nbsp;
+<img src='images/notification2.png' />
+<p class="img-caption"><strong>Figure 1.</strong> Screenshots of a foreground service's notification, showing the notification icon in the status bar (left) and the expanded view (right).</p>
+
+<p>You should only hold on to the "foreground service" status while your
+service is actually performing something the user is actively aware of. Once
+that is no longer true, you should release it by calling
+{@link android.app.Service#stopForeground stopForeground()}:</p>
+
+<pre>
+stopForeground(true);
+</pre>
+
+<p>For more information, see the documentation about <a
+href="{@docRoot}guide/topics/fundamentals/services.html#Foreground">Services</a> and
+<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
+
+
+<h3 id="audiofocus">Handling audio focus</h3>
+
+<p>Even though only one activity can run at any given time, Android is a
+multi-tasking environment. This poses a particular challenge to applications
+that use audio, because there is only one audio output and there may be several
+media services competing for its use. Before Android 2.2, there was no built-in
+mechanism to address this issue, which could in some cases lead to a bad user
+experience. For example, when a user is listening to
+music and another application needs to notify the user of something very important,
+the user might not hear the notification tone due to the loud music. Starting with
+Android 2.2, the platform offers a way for applications to negotiate their
+use of the device's audio output. This mechanism is called Audio Focus.</p>
+
+<p>When your application needs to output audio such as music or a notification, 
+you should always request audio focus. Once it has focus, it can use the sound output freely, but it should
+always listen for focus changes. If it is notified that it has lost the audio
+focus, it should immediately either kill the audio or lower it to a quiet level
+(known as "ducking"&mdash;there is a flag that indicates which one is appropriate) and only resume
+loud playback after it receives focus again.</p>
+
+<p>Audio Focus is cooperative in nature. That is, applications are expected
+(and highly encouraged) to comply with the audio focus guidelines, but the
+rules are not enforced by the system. If an application wants to play loud
+music even after losing audio focus, nothing in the system will prevent that.
+However, the user is more likely to have a bad experience and will be more
+likely to uninstall the misbehaving application.</p>
+
+<p>To request audio focus, you must call
+{@link android.media.AudioManager#requestAudioFocus requestAudioFocus()} from the {@link
+android.media.AudioManager}, as the example below demonstrates:</p>
+
+<pre>
+AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
+    AudioManager.AUDIOFOCUS_GAIN);
+
+if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+    // could not get audio focus.
+}
+</pre>
+
+<p>The first parameter to {@link android.media.AudioManager#requestAudioFocus requestAudioFocus()}
+is an {@link android.media.AudioManager.OnAudioFocusChangeListener
+AudioManager.OnAudioFocusChangeListener},
+whose {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange
+onAudioFocusChange()} method is called whenever there is a change in audio focus. Therefore, you
+should also implement this interface on your service and activities. For example:</p>
+
+<pre>
+class MyService extends Service
+                implements AudioManager.OnAudioFocusChangeListener {
+    // ....
+    public void onAudioFocusChange(int focusChange) {
+        // Do something based on focus change...
+    }
+}
+</pre>
+
+<p>The <code>focusChange</code> parameter tells you how the audio focus has changed, and
+can be one of the following values (they are all constants defined in
+{@link android.media.AudioManager AudioManager}):</p>
+
+<ul>
+<li>{@link android.media.AudioManager#AUDIOFOCUS_GAIN}: You have gained the audio focus.</li>
+
+<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS}: You have lost the audio focus for a
+presumably long time.
+You must stop all audio playback. Because you should expect not to have focus back
+for a long time, this would be a good place to clean up your resources as much
+as possible. For example, you should release the {@link android.media.MediaPlayer}.</li>
+
+<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}: You have
+temporarily lost audio focus, but should receive it back shortly. You must stop
+all audio playback, but you can keep your resources because you will probably get
+focus back shortly.</li>
+
+<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}: You have temporarily
+lost audio focus,
+but you are allowed to continue to play audio quietly (at a low volume) instead
+of killing audio completely.</li>
+</ul>
+
+<p>Here is an example implementation:</p>
+
+<pre>
+public void onAudioFocusChange(int focusChange) {
+    switch (focusChange) {
+        case AudioManager.AUDIOFOCUS_GAIN:
+            // resume playback
+            if (mMediaPlayer == null) initMediaPlayer();
+            else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
+            mMediaPlayer.setVolume(1.0f, 1.0f);
+            break;
+
+        case AudioManager.AUDIOFOCUS_LOSS:
+            // Lost focus for an unbounded amount of time: stop playback and release media player
+            if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+            break;
+
+        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+            // Lost focus for a short time, but we have to stop
+            // playback. We don't release the media player because playback
+            // is likely to resume
+            if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
+            break;
+
+        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+            // Lost focus for a short time, but it's ok to keep playing
+            // at an attenuated level
+            if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
+            break;
+    }
+}
+</pre>
+
+<p>Keep in mind that the audio focus APIs are available only with API level 8 (Android 2.2)
+and above, so if you want to support previous
+versions of Android, you should adopt a backward compatibility strategy that
+allows you to use this feature if available, and fall back seamlessly if not.</p>
+
+<p>You can achieve backward compatibility either by calling the audio focus methods by reflection
+or by implementing all the audio focus features in a separate class (say,
+<code>AudioFocusHelper</code>). Here is an example of such a class:</p>
+
+<pre>
+public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
+    AudioManager mAudioManager;
+
+    // other fields here, you'll probably hold a reference to an interface
+    // that you can use to communicate the focus changes to your Service
+
+    public AudioFocusHelper(Context ctx, /* other arguments here */) {
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        // ...
+    }
+
+    public boolean requestFocus() {
+        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
+            mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,
+            AudioManager.AUDIOFOCUS_GAIN);
+    }
+
+    public boolean abandonFocus() {
+        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
+            mAudioManager.abandonAudioFocus(this);
+    }
+
+    &#64;Override
+    public void onAudioFocusChange(int focusChange) {
+        // let your service know about the focus change
+    }
+}
+</pre>
+
+
+<p>You can create an instance of <code>AudioFocusHelper</code> class only if you detect that
+the system is running API level 8 or above. For example:</p>
+
+<pre>
+if (android.os.Build.VERSION.SDK_INT &gt;= 8) {
+    mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
+} else {
+    mAudioFocusHelper = null;
+}
+</pre>
+
+
+<h3 id="cleanup">Performing cleanup</h3>
+
+<p>As mentioned earlier, a {@link android.media.MediaPlayer} object can consume a significant
+amount of system resources, so you should keep it only for as long as you need and call
+{@link android.media.MediaPlayer#release release()} when you are done with it. It's important
+to call this cleanup method explicitly rather than rely on system garbage collection because
+it might take some time before the garbage collector reclaims the {@link android.media.MediaPlayer},
+as it's only sensitive to memory needs and not to shortage of other media-related resources.
+So, in the case when you're using a service, you should always override the
+{@link android.app.Service#onDestroy onDestroy()} method to make sure you are releasing
+the {@link android.media.MediaPlayer}:</p>
+
+<pre>
+public class MyService extends Service {
+   MediaPlayer mMediaPlayer;
+   // ...
+
+   &#64;Override
+   public void onDestroy() {
+       if (mMediaPlayer != null) mMediaPlayer.release();
+   }
+}
+</pre>
+
+<p>You should always look for other opportunities to release your {@link android.media.MediaPlayer}
+as well, apart from releasing it when being shut down. For example, if you expect not
+to be able to play media for an extended period of time (after losing audio focus, for example),
+you should definitely release your existing {@link android.media.MediaPlayer} and create it again
+later. On the
+other hand, if you only expect to stop playback for a very short time, you should probably
+hold on to your {@link android.media.MediaPlayer} to avoid the overhead of creating and preparing it
+again.</p>
+
+
+
+<h2 id="noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</h2>
+
+<p>Many well-written applications that play audio automatically stop playback when an event
+occurs that causes the audio to become noisy (ouput through external speakers). For instance,
+this might happen when a user is listening to music through headphones and accidentally
+disconnects the headphones from the device. However, this behavior does not happen automatically.
+If you don't implement this feature, audio plays out of the device's external speakers, which
+might not be what the user wants.</p>
+
+<p>You can ensure your app stops playing music in these situations by handling
+the {@link android.media.AudioManager#ACTION_AUDIO_BECOMING_NOISY} intent, for which you can register a receiver by
+adding the following to your manifest:</p>
+
+<pre>
+&lt;receiver android:name=".MusicIntentReceiver"&gt;
+   &lt;intent-filter&gt;
+      &lt;action android:name="android.media.AUDIO_BECOMING_NOISY" /&gt;
+   &lt;/intent-filter&gt;
+&lt;/receiver&gt;
+</pre>
+
+<p>This registers the <code>MusicIntentReceiver</code> class as a broadcast receiver for that
+intent. You should then implement this class:</p>
+
+<pre>
+public class MusicIntentReceiver implements android.content.BroadcastReceiver {
+   &#64;Override
+   public void onReceive(Context ctx, Intent intent) {
+      if (intent.getAction().equals(
+                    android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
+          // signal your service to stop playback
+          // (via an Intent, for instance)
+      }
+   }
+}
+</pre>
+
+
+
+
+<h2 id="viacontentresolver">Retrieving Media from a Content Resolver</h2>
+
+<p>Another feature that may be useful in a media player application is the ability to
+retrieve music that the user has on the device. You can do that by querying the {@link
+android.content.ContentResolver} for external media:</p>
+
+<pre>
+ContentResolver contentResolver = getContentResolver();
+Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+Cursor cursor = contentResolver.query(uri, null, null, null, null);
+if (cursor == null) {
+    // query failed, handle error.
+} else if (!cursor.moveToFirst()) {
+    // no media on the device
+} else {
+    int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
+    int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
+    do {
+       long thisId = cursor.getLong(idColumn);
+       String thisTitle = cursor.getString(titleColumn);
+       // ...process entry...
+    } while (cursor.moveToNext());
+}
+</pre>
+
+<p>To use this with the {@link android.media.MediaPlayer}, you can do this:</p>
+
+<pre>
+long id = /* retrieve it from somewhere */;
+Uri contentUri = ContentUris.withAppendedId(
+        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
+
+mMediaPlayer = new MediaPlayer();
+mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+mMediaPlayer.setDataSource(getApplicationContext(), contentUri);
+
+// ...prepare and start...
+</pre>
+
+
+
+<h2 id="jetcontent">Playing JET content</h2>
+
+<p>The Android platform includes a JET engine that lets you add interactive playback of JET audio
+content in your applications. You can create JET content for interactive playback using the
+JetCreator authoring application that ships with the SDK. To play and manage JET content from your
+application, use the {@link android.media.JetPlayer JetPlayer} class.</p>
+
+<p>For a description of JET concepts and instructions on how to use the JetCreator authoring tool,
+see the <a href="{@docRoot}guide/topics/media/jet/jetcreator_manual.html">JetCreator User
+Manual</a>. The tool is available on Windows, OS X, and Linux platforms (Linux does not
+support auditioning of imported assets like with the Windows and OS X versions).
+</p>
+
+<p>Here's an example of how to set up JET playback from a <code>.jet</code> file stored on the SD card:</p>
+
+<pre>
+JetPlayer jetPlayer = JetPlayer.getJetPlayer();
+jetPlayer.loadJetFile("/sdcard/level1.jet");
 byte segmentId = 0;
 
 // queue segment 5, repeat once, use General MIDI, transpose by -1 octave
-myJet.queueJetSegment(5, -1, 1, -1, 0, segmentId++);
+jetPlayer.queueJetSegment(5, -1, 1, -1, 0, segmentId++);
 // queue segment 2
-myJet.queueJetSegment(2, -1, 0, 0, 0, segmentId++);
+jetPlayer.queueJetSegment(2, -1, 0, 0, 0, segmentId++);
 
-myJet.play();
+jetPlayer.play();
 </pre>
 
-<p>The SDK includes an example application &mdash; JetBoy &mdash; that shows how to use {@link android.media.JetPlayer JetPlayer} to create an interactive music soundtrack in your game. It also illustrates how to use JET events to synchronize music and game logic. The application is located at <code>&lt;sdk&gt;/platforms/android-1.5/samples/JetBoy</code>.
+<p>The SDK includes an example application &mdash; JetBoy &mdash; that shows how to use {@link
+android.media.JetPlayer JetPlayer} to create an interactive music soundtrack in your game. It also
+illustrates how to use JET events to synchronize music and game logic. The application is located at
+<code>&lt;sdk&gt;/platforms/android-1.5/samples/JetBoy</code>.</p>
 
-<h2 id="capture">Audio Capture</h2>
-<p>Audio capture from the device is a bit more complicated than audio/video playback, but still fairly simple:</p>
+
+<h2 id="audiocapture">Performing Audio Capture</h2>
+
+<p>Audio capture from the device is a bit more complicated than audio and video playback, but still fairly simple:</p>
 <ol>
-  <li>Create a new instance of {@link android.media.MediaRecorder android.media.MediaRecorder} using <code>new</code></li>
+  <li>Create a new instance of {@link android.media.MediaRecorder android.media.MediaRecorder}.</li>
   <li>Set the audio source using
         {@link android.media.MediaRecorder#setAudioSource MediaRecorder.setAudioSource()}. You will probably want to use
-  <code>MediaRecorder.AudioSource.MIC</code></li>
+  <code>MediaRecorder.AudioSource.MIC</code>.</li>
   <li>Set output file format using
-        {@link android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}
+        {@link android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}.
   </li>
   <li>Set output file name using
-        {@link android.media.MediaRecorder#setOutputFile MediaRecorder.setOutputFile()}
+        {@link android.media.MediaRecorder#setOutputFile MediaRecorder.setOutputFile()}.
   </li>
-  <li>Set the audio encoder using 
-        {@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()}
+  <li>Set the audio encoder using
+        {@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()}.
   </li>
   <li>Call {@link android.media.MediaRecorder#prepare MediaRecorder.prepare()}
    on the MediaRecorder instance.</li>
-  <li>To start audio capture, call 
+  <li>To start audio capture, call
   {@link android.media.MediaRecorder#start MediaRecorder.start()}. </li>
   <li>To stop audio capture, call {@link android.media.MediaRecorder#stop MediaRecorder.stop()}.
   <li>When you are done with the MediaRecorder instance, call
@@ -354,3 +968,4 @@
 </pre>
 
 
+
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index a996ccc..ea778c1 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -335,80 +335,101 @@
     </tr>
     <tr id="SmallestScreenWidthQualifier">
       <td>Smallest screen width</td>
-      <td>Examples:<br/>
+      <td><code>sw&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
         <code>sw320dp</code><br/>
         <code>sw600dp</code><br/>
         <code>sw720dp</code><br/>
         etc.
       </td>
       <td>
-        <p>Specifies a minimum "smallest screen width," in "dp" units, at which the resource
-          should be used.  This configuration value represents the base screen size
-          of the device, regardless of the orientation of the display.  It is based
-          on the smallest width the application will have in which to perform its
-          UI layout (in dp units) regardless of the orientation of the screen.  The
-          value here takes into account screen decorations so if the device has some
-          persistent UI elements on the left or right edge of the display it must
-          present a value here that is smaller than the real screen size, accounting
-          for these UI elements reducing the application's available space.</p>
-        <p>Some values you may use here for common screen sizes:</p>
+        <p>Specifies the "smallest width" in {@code dp} units that must be available to your
+        application in order for the resources to be used, regardless of the screen's current
+        orientation. For example, if your layout requires that its shortest side be at least 600
+        dp in length at all times, then you can use this to create the layout resources, {@code
+        res/layout-sw600dp/}, and the system will use them only when the shortest side of
+        available screen space it at least 600dp.</p>
+        <p>The width against which the system compares your value takes into account screen
+        decorations and system UI. For example, if the device has some persistent UI elements on the
+        left or right edge of the display, the system declares its own available width as one that
+        is smaller than the actual screen size, accounting for these UI elements because those are
+        screen pixels not available for your UI. Thus, the value you use should be the actual
+        smallest width required by your layout.</p>
+        <p>Some values you might use here for common screen sizes:</p>
         <ul>
-          <li>240x320 ldpi (QVGA phone): 320
-          <li>320x480 mdpi (phone): 320
-          <li>480x800 hdpi (high density phone): 320
-          <li>480x800 mdpi (tablet/phone): 480
-          <li>600x1024 mdpi (7" tablet): 600
-          <li>720x1280 mdpi (10" tablet): 720
+          <li>320, for devices with screen configurations such as:
+            <ul>
+              <li>240x320 ldpi (QVGA handset)</li>
+              <li>320x480 mdpi (handset)</li>
+              <li>480x800 hdpi (high density handset)</li>
+            </ul>
+          </li>
+          <li>480, for screens such as 480x800 mdpi (tablet/handset).</li>
+          <li>600, for screens such as 600x1024 mdpi (7" tablet).</li>
+          <li>720, for screens such as 720x1280 mdpi (10" tablet).</li>
         </ul>
-        <p><em>Added in API Level 13.</em></p>
-        <p>Also see the {@link android.content.res.Configuration#smallestScreenWidthDp}
-          configuration field, which holds the current smallest screen width.</p>
+        <p>When your application provides multiple resource directories with different values for
+        this qualifier, the system uses the one closest to (without exceeding) the smallest width
+        for the available space. </p>
+        <p><em>Added in API level 13.</em></p>
+        <p>Also see the <a
+        href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+        android:requiresSmallestWidthDp}</a> attribute, which declares the smallest available width
+        with which your application is compatible, and the {@link
+        android.content.res.Configuration#smallestScreenWidthDp} configuration field, which holds
+        the current smallest screen width for the device.</p>
       </td>
     </tr>
     <tr id="ScreenWidthQualifier">
       <td>Screen width</td>
-      <td>Examples:<br/>
+      <td><code>w&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
         <code>w720dp</code><br/>
         <code>w1024dp</code><br/>
         etc.
       </td>
       <td>
-        <p>Specifies a minimum screen width, in "dp" units, at which the resource
-          should be used.  This configuration value will change when the orientation
-          changes between landscape and portrait to match the current actual width.
-          When multiple screen width configurations are available, the closest to
-          the current screen width will be used.  The
-          value here takes into account screen decorations so if the device has some
-          persistent UI elements on the left or right edge of the display it must
-          present a value here that is smaller than the real screen size, accounting
-          for these UI elements reducing the application's available space.</p>
-        <p><em>Added in API Level 13.</em></p>
+        <p>Specifies a minimum screen width, in {@code dp} units at which the resource
+          should be used&mdash;defined by the <code>&lt;N&gt;</code> value.  This
+          configuration value will change when the orientation
+          changes between landscape and portrait to match the current actual width.</p>
+        <p>When your application provides multiple resource directories with different values
+          for this configuration, the system uses the one closest to (without exceeding)
+          the device's current screen width.  The
+          value here takes into account screen decorations, so if the device has some
+          persistent UI elements on the left or right edge of the display, it
+          uses a value for the width that is smaller than the real screen size, accounting
+          for these UI elements and reducing the application's available space.</p>
+        <p><em>Added in API level 13.</em></p>
         <p>Also see the {@link android.content.res.Configuration#screenWidthDp}
           configuration field, which holds the current screen width.</p>
       </td>
     </tr>
     <tr id="ScreenHeightQualifier">
       <td>Screen height</td>
-      <td>Examples:<br/>
+      <td><code>h&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
         <code>h720dp</code><br/>
         <code>h1024dp</code><br/>
         etc.
       </td>
       <td>
-        <p>Specifies a minimum screen height, in "dp" units, at which the resource
-          should be used.  This configuration value will change when the orientation
-          changes between landscape and portrait to match the current actual height.
-          When multiple screen height configurations are available, the closest to
-          the current screen height will be used.  The
-          value here takes into account screen decorations so if the device has some
-          persistent UI elements on the left or right edge of the display it must
-          present a value here that is smaller than the real screen size, accounting
-          for these UI elements reducing the application's available space.  Screen
+        <p>Specifies a minimum screen height, in "dp" units at which the resource
+          should be used&mdash;defined by the <code>&lt;N&gt;</code> value.  This
+          configuration value will change when the orientation
+          changes between landscape and portrait to match the current actual height.</p>
+        <p>When your application provides multiple resource directories with different values
+          for this configuration, the system uses the one closest to (without exceeding)
+          the device's current screen height.  The
+          value here takes into account screen decorations, so if the device has some
+          persistent UI elements on the top or bottom edge of the display, it uses
+          a value for the height that is smaller than the real screen size, accounting
+          for these UI elements and reducing the application's available space.  Screen
           decorations that are not fixed (such as a phone status bar that can be
           hidden when full screen) are <em>not</em> accounted for here, nor are
-          window decorations like title bar, so applications must be prepared to
+          window decorations like the title bar or action bar, so applications must be prepared to
           deal with a somewhat smaller space than they specify.
-        <p><em>Added in API Level 13.</em></p>
+        <p><em>Added in API level 13.</em></p>
         <p>Also see the {@link android.content.res.Configuration#screenHeightDp}
           configuration field, which holds the current screen width.</p>
       </td>
@@ -444,9 +465,9 @@
         medium-density HVGA screen. The minimum layout size for this screen configuration
         is approximately 720x960 dp units.  In most cases, devices with extra large
         screens would be too large to carry in a pocket and would most likely
-        be tablet-style devices. <em>Added in API Level 9.</em></li>
+        be tablet-style devices. <em>Added in API level 9.</em></li>
         </ul>
-        <p><em>Added in API Level 4.</em></p>
+        <p><em>Added in API level 4.</em></p>
         <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
 Screens</a> for more information.</p>
         <p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -465,7 +486,7 @@
           <li>{@code long}: Long screens, such as WQVGA, WVGA, FWVGA</li>
           <li>{@code notlong}: Not long screens, such as QVGA, HVGA, and VGA</li>
         </ul>
-        <p><em>Added in API Level 4.</em></p>
+        <p><em>Added in API level 4.</em></p>
         <p>This is based purely on the aspect ratio of the screen (a "long" screen is wider). This
 is not related to the screen orientation.</p>
         <p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -503,7 +524,7 @@
           <li>{@code car}: Device is in a car dock</li>
           <li>{@code desk}: Device is in a desk dock</li>
         </ul>
-        <p><em>Added in API Level 8.</em></p>
+        <p><em>Added in API level 8.</em></p>
         <p>This can change during the life of your application if the user places the device in a
 dock. You can enable or disable this mode using {@link
 android.app.UiModeManager}. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
@@ -521,7 +542,7 @@
           <li>{@code night}: Night time</li>
           <li>{@code notnight}: Day time</li>
         </ul>
-        <p><em>Added in API Level 8.</em></p>
+        <p><em>Added in API level 8.</em></p>
         <p>This can change during the life of your application if night mode is left in
 auto mode (default), in which case the mode changes based on the time of day.  You can enable
 or disable this mode using {@link android.app.UiModeManager}. See <a
@@ -549,7 +570,7 @@
           <li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
 to match the device density.</li>
         </ul>
-        <p><em>Added in API Level 4.</em></p>
+        <p><em>Added in API level 4.</em></p>
         <p>There is thus a 3:4:6:8 scaling ratio between the four densities, so a 9x9 bitmap
          in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
         <p>When Android selects which resource files to use,
@@ -689,17 +710,17 @@
     </tr>
 -->
     <tr id="VersionQualifier">
-      <td>Platform Version (API Level)</td>
+      <td>Platform Version (API level)</td>
       <td>Examples:<br/>
         <code>v3</code><br/>
         <code>v4</code><br/>
         <code>v7</code><br/>
         etc.</td>
       <td>
-        <p>The API Level supported by the device. For example, <code>v1</code> for API Level
-1 (devices with Android 1.0 or higher) and <code>v4</code> for API Level 4 (devices with Android
+        <p>The API level supported by the device. For example, <code>v1</code> for API level
+1 (devices with Android 1.0 or higher) and <code>v4</code> for API level 4 (devices with Android
 1.6 or higher). See the <a
-href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> document for more information
+href="{@docRoot}guide/appendix/api-levels.html">Android API levels</a> document for more information
 about these values.</p>
         <p class="caution"><strong>Caution:</strong> Android 1.5 and 1.6 only match resources
 with this qualifier when it exactly matches the platform version. See the section below about <a
@@ -863,7 +884,7 @@
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
 minSdkVersion}</a> is set to 4, and you qualify all of your drawable resources using <a
 href="#NightQualifier">night mode</a> ({@code night} or {@code notnight}, which were added in API
-Level 8), then an API Level 4 device cannot access your drawable resources and will crash. In this
+Level 8), then an API level 4 device cannot access your drawable resources and will crash. In this
 case, you probably want {@code notnight} to be your default resources, so you should exclude that
 qualifier so your drawable resources are in either {@code drawable/} or {@code drawable-night/}.</p>
 
@@ -896,7 +917,7 @@
     <dd>{@code long} and {@code notlong}</dd>
 </dl>
 
-<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API Level 3) and
+<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API level 3) and
 lower does not support them. If you use these configuration qualifiers and do not provide
 corresponding default resources, then an Android 1.5 device might use any one of the resource
 directories named with the above screen configuration qualifiers, because it ignores these
@@ -926,9 +947,9 @@
     <p>You need SDK Tools, Revision 6 (or greater), because it includes a new packaging tool that
 automatically applies an appropriate <a href="#VersionQualifier">version qualifier</a> to any
 resource directory named with a qualifier that does not exist in Android 1.0. For example, because
-the density qualifier was introduced in Android 1.6 (API Level 4), when the packaging tool
+the density qualifier was introduced in Android 1.6 (API level 4), when the packaging tool
 encounters a resource directory using the density qualifier, it adds {@code v4} to the directory
-name to ensure that older versions do not use those resources (only API Level 4 and higher support
+name to ensure that older versions do not use those resources (only API level 4 and higher support
 that qualifier). Thus, by putting your medium-density resources in a directory <em>without</em> the
 {@code mdpi} qualifier, they are still accessible by Android 1.5, and any device that supports the
 density qualifer and has a medium-density screen also uses the default resources (which are mdpi)
@@ -937,7 +958,7 @@
 </li>
 </ol>
 
-<p class="note"><strong>Note:</strong> Later versions of Android, such as API Level 8,
+<p class="note"><strong>Note:</strong> Later versions of Android, such as API level 8,
 introduce other configuration qualifiers that older version do not support. To provide the best
 compatibility, you should always include a set of default resources for each type of resource
 that your application uses, as discussed above to provide the best device compatibility.</p>
@@ -1068,7 +1089,7 @@
 
 <p>The correct behavior is for the system to match resources marked with a <a
 href="#VersionQualifier">version qualifier</a> equal
-to or less than the platform version on the device, but on Android 1.5 and 1.6, (API Level 3 and 4),
+to or less than the platform version on the device, but on Android 1.5 and 1.6, (API level 3 and 4),
 there is a bug that causes the system to match resources marked with the version qualifier
 only when it exactly matches the version on the device.</p>
 
diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd
index 7ac5ff1..218511b 100644
--- a/docs/html/guide/topics/search/index.jd
+++ b/docs/html/guide/topics/search/index.jd
@@ -52,7 +52,13 @@
 <p class="note"><strong>Note</strong>: The search framework does <em>not</em> provide APIs to
 search your data. To perform a search, you need to use APIs appropriate for your data. For example,
 if your data is stored in an SQLite database, you should use the {@link android.database.sqlite}
-APIs to perform searches.</p>
+APIs to perform searches.
+<br/><br/>
+Also, there is no guarantee that every device provides a dedicated SEARCH button to invoke the
+search interface in your application. When using the search dialog or a custom interface, you
+must always provide a search button in your UI that activates the search interface. For more
+information, see <a href="search-dialog.html#InvokingTheSearchDialog">Invoking the search
+dialog</a>.</p>
 
 <p>The following documents show you how to use Android's framework to implement search:</p>
 
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index af6c8f2..d869a44 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -17,29 +17,30 @@
 
 <h2>In this document</h2>
 <ol>
-<li><a href="#TheBasics">The Basics</a></li>
-<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
-<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
-  <ol>
-    <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
-    <li><a href="#EnableSearch">Enabling the search dialog and search widget</a></li>
-    <li><a href="#PerformingSearch">Performing a search</a></li>
-  </ol>
-</li>
-<li><a href="#UsingTheSearchDialog">Using the Search Dialog</a>
-  <ol>
-    <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
-    <li><a href="#SearchContextData">Passing search context data</a></li>
-  </ol>
-</li>
-<li><a href="#UsingSearchWidget">Using the Search Widget</a>
-  <ol>
-    <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
-    <li><a href="#WidgetFeatures">Other search widget features</a></li>
-  </ol>
-</li>
-<li><a href="#VoiceSearch">Adding Voice Search</a></li>
-<li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
+  <li><a href="#TheBasics">The Basics</a></li>
+  <li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
+  <li><a href="#SearchableActivity">Creating a Searchable Activity</a>
+    <ol>
+      <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
+      <li><a href="#PerformingSearch">Performing a search</a></li>
+    </ol>
+  </li>
+  <li><a href="#SearchDialog">Using the Search Dialog</a>
+    <ol>
+      <li><a href="#InvokingTheSearchDialog">Invoking the search dialog</a></li>
+      <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
+      <li><a href="#SearchContextData">Passing search context data</a></li>
+    </ol>
+  </li>
+  <li><a href="#UsingSearchWidget">Using the Search Widget</a>
+    <ol>
+      <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
+      <li><a href="#WidgetFeatures">Other search widget features</a></li>
+      <li><a href="#UsingBoth">Using both the widget and the dialog</a></li>
+    </ol>
+  </li>
+  <li><a href="#VoiceSearch">Adding Voice Search</a></li>
+  <li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
 </ol>
 
 <h2>Key classes</h2>
@@ -494,13 +495,13 @@
 
 <h3 id="InvokingTheSearchDialog">Invoking the search dialog</h3>
 
-<p>As mentioned above, the device SEARCH button and {@link android.app.Activity#onSearchRequested
-onSearchRequested()} method will open the search dialog, as long as the current activity
-has declared the searchable activity to use, as shown in the previous section.</p>
+<p>As mentioned above, the device SEARCH button will open the search dialog as long as the current
+activity has declared in the manifest the searchable activity to use.</p>
 
-<p>However, you should not assume that a SEARCH button is available on the user's device. You
-should always provide another search button in your UI that activates the search dialog by calling
-{@link android.app.Activity#onSearchRequested()}.</p>
+<p>However, some devices do not include a dedicated SEARCH button, so you should not assume that
+it's always available. When using the search dialog, you must <strong>always provide another search
+button in your UI</strong> that activates the search dialog by calling {@link
+android.app.Activity#onSearchRequested()}.</p>
 
 <p>For instance, you should either provide a menu item in your <a
 href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your
@@ -510,12 +511,6 @@
 medium and high density screens, which you can use for your search menu item or button (low-density
 screens scale-down the hdpi image by one half). </p>
 
-<!-- ... maybe this should go into the Creating Menus document ....
-<p>If you chose to provide a shortcut key for the menu item,  using {@link
-android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
-key character, representing the default search key.</p>
--->
-
 <p>You can also enable "type-to-search" functionality, which activates the search dialog when the
 user starts typing on the keyboard&mdash;the keystrokes are inserted into the search dialog. You can
 enable type-to-search in your activity by calling
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index 0e35637..2e172f5 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -54,6 +54,11 @@
         </li>
       </ol>
 
+      <h2>Download</h2>
+      <ol>
+        <li><a href="https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package</a></li>
+      </ol>
+
 
       <h2>See also</h2>
 
diff --git a/docs/html/guide/topics/wireless/bluetooth.jd b/docs/html/guide/topics/wireless/bluetooth.jd
index 48632ea..0af1d2c 100644
--- a/docs/html/guide/topics/wireless/bluetooth.jd
+++ b/docs/html/guide/topics/wireless/bluetooth.jd
@@ -1,57 +1,61 @@
 page.title=Bluetooth
 @jd:body
 
-<div id="qv-wrapper">
-<div id="qv">
-
-  <h2>Quickview</h2>
-  <ul>
+<div id="qv-wrapper"> 
+<div id="qv"> 
+ 
+  <h2>Quickview</h2> 
+  <ul> 
     <li>Android's bluetooth APIs allow your application to perform wireless data transactions with
-other devices</li>
-  </ul>
-
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#TheBasics">The Basics</a></li>
-    <li><a href="#Permissions">Bluetooth Permissions</a></li>
-    <li><a href="#SettingUp">Setting Up Bluetooth</a></li>
-    <li><a href="#FindingDevices">Finding Devices</a>
-      <ol>
-        <li><a href="#QueryingPairedDevices">Querying paired devices</a></li>
-        <li><a href="#DiscoveringDevices">Discovering devices</a></li>
-      </ol></li>
-    <li><a href="#ConnectingDevices">Connecting Devices</a>
-      <ol>
-        <li><a href="#ConnectingAsAServer">Connecting as a server</a></li>
-        <li><a href="#ConnectingAsAClient">Connecting as a client</a></li>
-      </ol></li>
+other devices</li> 
+  </ul> 
+ 
+  <h2>In this document</h2> 
+  <ol> 
+    <li><a href="#TheBasics">The Basics</a></li> 
+    <li><a href="#Permissions">Bluetooth Permissions</a></li> 
+    <li><a href="#SettingUp">Setting Up Bluetooth</a></li> 
+    <li><a href="#FindingDevices">Finding Devices</a> 
+      <ol> 
+        <li><a href="#QueryingPairedDevices">Querying paired devices</a></li> 
+        <li><a href="#DiscoveringDevices">Discovering devices</a></li> 
+      </ol></li> 
+    <li><a href="#ConnectingDevices">Connecting Devices</a> 
+      <ol> 
+        <li><a href="#ConnectingAsAServer">Connecting as a server</a></li> 
+        <li><a href="#ConnectingAsAClient">Connecting as a client</a></li> 
+      </ol></li> 
     <li><a href="#ManagingAConnection">Managing a Connection</a></li>
-  </ol>
-
-  <h2>Key classes</h2>
-  <ol>
-    <li>{@link android.bluetooth.BluetoothAdapter}</li>
-    <li>{@link android.bluetooth.BluetoothDevice}</li>
-    <li>{@link android.bluetooth.BluetoothSocket}</li>
-    <li>{@link android.bluetooth.BluetoothServerSocket}</li>
-  </ol>
-
-  <h2>Related samples</h2>
-  <ol>
-    <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li>
-  </ol>
-
-</div>
-</div>
-
-
+    <li><a href="#Profiles">Working with Profiles</a> 
+      <ol>
+        <li><a href="#AT-Commands">Vendor-specific AT commands</a>
+      </ol></li>
+  </ol> 
+ 
+  <h2>Key classes</h2> 
+  <ol> 
+    <li>{@link android.bluetooth.BluetoothAdapter}</li> 
+    <li>{@link android.bluetooth.BluetoothDevice}</li> 
+    <li>{@link android.bluetooth.BluetoothSocket}</li> 
+    <li>{@link android.bluetooth.BluetoothServerSocket}</li> 
+  </ol> 
+ 
+  <h2>Related samples</h2> 
+  <ol> 
+    <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li> 
+  </ol> 
+ 
+</div> 
+</div> 
+ 
+ 
 <p>The Android platform includes support for the Bluetooth network stack,
 which allows a device to wirelessly exchange data with other Bluetooth devices.
 The application framework provides access to the Bluetooth functionality through
 the Android Bluetooth APIs. These APIs let applications wirelessly
 connect to other Bluetooth devices, enabling point-to-point and multipoint
-wireless features.</p>
-
+wireless features.</p> 
+ 
 <p>Using the Bluetooth APIs, an Android application can perform the
 following:</p>
 <ul>
@@ -66,17 +70,17 @@
 
 <h2 id="TheBasics">The Basics</h2>
 
-<p>This document describes how to us the Android Bluetooth APIs to accomplish
+<p>This document describes how to use the Android Bluetooth APIs to accomplish
 the four major tasks necessary to communicate using Bluetooth: setting up
 Bluetooth, finding devices that are either paired or available in the local
-area, connecting devices, and transferring data between devices.</p>
-
+area, connecting devices, and transferring data between devices.</p> 
+ 
 <p>All of the Bluetooth APIs are available in the {@link android.bluetooth}
-package. Here's a summary of the classes you will need to create Bluetooth
-connections:</p>
-
-<dl>
-<dt>{@link android.bluetooth.BluetoothAdapter}</dt>
+package. Here's a summary of the classes and interfaces you will need to create Bluetooth
+connections:</p> 
+ 
+<dl> 
+<dt>{@link android.bluetooth.BluetoothAdapter}</dt> 
 <dd>Represents the local Bluetooth adapter (Bluetooth radio). The
 {@link android.bluetooth.BluetoothAdapter} is the entry-point for all Bluetooth
 interaction. Using this,
@@ -84,51 +88,72 @@
 devices, instantiate a {@link android.bluetooth.BluetoothDevice} using a known
 MAC address, and create a {@link android.bluetooth.BluetoothServerSocket} to
 listen for communications
-from other devices.</dd>
-
-<dt>{@link android.bluetooth.BluetoothDevice}</dt>
+from other devices.</dd> 
+ 
+<dt>{@link android.bluetooth.BluetoothDevice}</dt> 
 <dd>Represents a remote Bluetooth device. Use this to request a connection
 with a remote device through a {@link android.bluetooth.BluetoothSocket} or
 query information about the
-device such as its name, address, class, and bonding state.</dd>
-
-<dt>{@link android.bluetooth.BluetoothSocket}</dt>
+device such as its name, address, class, and bonding state.</dd> 
+ 
+<dt>{@link android.bluetooth.BluetoothSocket}</dt> 
 <dd>Represents the interface for a Bluetooth socket (similar to a TCP
 {@link java.net.Socket}). This is the connection point that allows
 an application to exchange data with another Bluetooth device via InputStream
-and OutputStream.</dd>
-
-<dt>{@link android.bluetooth.BluetoothServerSocket}</dt>
+and OutputStream.</dd> 
+ 
+<dt>{@link android.bluetooth.BluetoothServerSocket}</dt> 
 <dd>Represents an open server socket that listens for incoming requests
 (similar to a TCP {@link java.net.ServerSocket}). In order to connect two
 Android devices, one device must open a server socket with this class. When a
 remote Bluetooth device makes a connection request to the this device, the
 {@link android.bluetooth.BluetoothServerSocket} will return a connected {@link
 android.bluetooth.BluetoothSocket} when the
-connection is accepted.</dd>
-
-<dt>{@link android.bluetooth.BluetoothClass}</dt>
+connection is accepted.</dd> 
+ 
+<dt>{@link android.bluetooth.BluetoothClass}</dt> 
 <dd>Describes the general characteristics and capabilities of a Bluetooth
 device. This is a read-only set of properties that define the device's major and
 minor device classes and its services. However, this does not reliably describe
 all Bluetooth profiles and services supported by the device, but is useful as a
-hint to the device type.</dd>
-</dl>
+hint to the device type.</dd> 
+ 
+<dt>{@link android.bluetooth.BluetoothProfile}</dt> <dd>An interface that
+represents a Bluetooth profile. A <em>Bluetooth profile</em> is a wireless
+interface specification for Bluetooth-based communication between devices. An
+example is the Hands-Free profile.  For more discussion of profiles, see <a
+href="#Profiles">Working with Profiles</a></dd> 
 
+<dt>{@link android.bluetooth.BluetoothHeadset}</dt> <dd>Provides support for
+Bluetooth headsets to be used with mobile phones. This includes both  Bluetooth
+Headset and Hands-Free (v1.5) profiles.</dd> 
 
+<dt>{@link android.bluetooth.BluetoothA2dp}</dt> <dd> Defines how high quality
+audio can be streamed from one device to another over a Bluetooth connection.
+"A2DP" stands for Advanced Audio Distribution Profile.</dd> 
 
+<dt>{@link android.bluetooth.BluetoothProfile.ServiceListener}</dt> 
 
-<h2 id="Permissions">Bluetooth Permissions</h2>
-
+<dd>An interface that notifies {@link android.bluetooth.BluetoothProfile} IPC
+clients when they have  been connected to or disconnected from the service (that
+is, the internal service that runs a particular profile). </dd> 
+ 
+</dl> 
+ 
+ 
+ 
+ 
+<h2 id="Permissions">Bluetooth Permissions</h2> 
+ 
 <p>In order to use Bluetooth features in your application, you need to declare
 at least one of two Bluetooth permissions: {@link
 android.Manifest.permission#BLUETOOTH} and {@link
-android.Manifest.permission#BLUETOOTH_ADMIN}.</p>
-
+android.Manifest.permission#BLUETOOTH_ADMIN}.</p> 
+ 
 <p>You must request the {@link android.Manifest.permission#BLUETOOTH} permission
 in order to perform any Bluetooth communication, such as requesting a
-connection, accepting a connection, and transferring data.</p>
-
+connection, accepting a connection, and transferring data.</p> 
+ 
 <p>You must request the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
 permission in order to initiate device discovery or manipulate Bluetooth
 settings. Most applications need this permission solely for the
@@ -136,40 +161,40 @@
 permission should not be used, unless the application is a "power manager" that
 will modify Bluetooth settings upon user request. <strong>Note:</strong> If you
 use {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission, then must
-also have the {@link android.Manifest.permission#BLUETOOTH} permission.</p>
-
+also have the {@link android.Manifest.permission#BLUETOOTH} permission.</p> 
+ 
 <p>Declare the Bluetooth permission(s) in your application manifest file. For
-example:</p>
-
-<pre>
+example:</p> 
+ 
+<pre> 
 &lt;manifest ... >
   &lt;uses-permission android:name="android.permission.BLUETOOTH" />
   ...
 &lt;/manifest>
-</pre>
-
+</pre> 
+ 
 <p>See the <a
-href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission></a>
-reference for more information about declaring application permissions.</p>
-
-
-<h2 id="SettingUp">Setting Up Bluetooth</h2>
-
-<div class="figure" style="width:200px">
-<img src="{@docRoot}images/bt_enable_request.png" />
+href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission></a> 
+reference for more information about declaring application permissions.</p> 
+ 
+ 
+<h2 id="SettingUp">Setting Up Bluetooth</h2> 
+ 
+<div class="figure" style="width:200px"> 
+<img src="{@docRoot}images/bt_enable_request.png" /> 
 <strong>Figure 1:</strong> The enabling Bluetooth dialog.
-</div>
-
+</div> 
+ 
 <p>Before your application can communicate over Bluetooth, you need to verify
-that Bluetooth is supported on the device, and if so, ensure that it is enabled.</p>
-
+that Bluetooth is supported on the device, and if so, ensure that it is enabled.</p> 
+ 
 <p>If Bluetooth is not supported, then you should gracefully disable any
 Bluetooth features. If Bluetooth is supported, but disabled, then you can request that the
 user enable Bluetooth without leaving your application. This setup is
-accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.</p>
-
-
-<ol>
+accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.</p> 
+ 
+ 
+<ol> 
 <li>Get the {@link android.bluetooth.BluetoothAdapter}
 <p>The {@link android.bluetooth.BluetoothAdapter} is required for any and all Bluetooth
 activity. To get the {@link android.bluetooth.BluetoothAdapter}, call the static {@link
@@ -178,15 +203,15 @@
 Bluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter for the
 entire system, and your application can interact with it using this object. If
 {@link android.bluetooth.BluetoothAdapter#getDefaultAdapter()} returns null,
-then the device does not support Bluetooth and your story ends here. For example:</p>
-<pre>
+then the device does not support Bluetooth and your story ends here. For example:</p> 
+<pre> 
 BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 if (mBluetoothAdapter == null) {
     // Device does not support Bluetooth
 }
-</pre>
-</li>
-
+</pre> 
+</li> 
+ 
 <li>Enable Bluetooth
 <p>Next, you need to ensure that Bluetooth is enabled. Call {@link
 android.bluetooth.BluetoothAdapter#isEnabled()} to check whether Bluetooth is
@@ -195,26 +220,26 @@
 android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()}
 with the {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_ENABLE} action Intent.
 This will issue a request to enable Bluetooth through the system settings (without
-stopping your application). For example:</p>
-<pre>
+stopping your application). For example:</p> 
+<pre> 
 if (!mBluetoothAdapter.isEnabled()) {
     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
 }
-</pre>
-
+</pre> 
+ 
 <p>A dialog will appear requesting user permission to enable Bluetooth, as shown
 in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth
-and focus will return to your application once the process completes (or fails).</p>
+and focus will return to your application once the process completes (or fails).</p> 
 <p>If enabling Bluetooth succeeds, your Activity will receive the {@link
 android.app.Activity#RESULT_OK} result code in the {@link
 android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()}
 callback. If Bluetooth was not enabled
 due to an error (or the user responded "No") then the result code will be {@link
-android.app.Activity#RESULT_CANCELED}.</p>
-</li>
-</ol>
-
+android.app.Activity#RESULT_CANCELED}.</p> 
+</li> 
+</ol> 
+ 
 <p>Optionally, your application can also listen for the
 {@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED} broadcast Intent, which
 the system will broadcast whenever the Bluetooth state has changed. This broadcast contains
@@ -226,21 +251,21 @@
 android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}, and {@link
 android.bluetooth.BluetoothAdapter#STATE_OFF}. Listening for this
 broadcast can be useful to detect changes made to the Bluetooth state while your
-app is running.</p>
-
+app is running.</p> 
+ 
 <p class="note"><strong>Tip:</strong> Enabling discoverability will automatically
 enable Bluetooth. If you plan to consistently enable device discoverability before
 performing Bluetooth activity, you can skip
 step 2 above. Read about <a href="#EnablingDiscoverability">enabling discoverability</a>,
-below.</p>
-
-
-<h2 id="FindingDevices">Finding Devices</h2>
-
+below.</p> 
+ 
+ 
+<h2 id="FindingDevices">Finding Devices</h2> 
+ 
 <p>Using the {@link android.bluetooth.BluetoothAdapter}, you can find remote Bluetooth
 devices either through device discovery or by querying the list of paired (bonded)
-devices.</p>
-
+devices.</p> 
+ 
 <p>Device discovery is a scanning procedure that searches the local area for
 Bluetooth enabled devices and then requesting some information about each one
 (this is sometimes referred to as "discovering," "inquiring" or "scanning").
@@ -249,15 +274,15 @@
 discoverable, it will respond to the discovery request by sharing some
 information, such as the device name, class, and its unique MAC address. Using
 this information, the device performing discovery can then choose to initiate a
-connection to the discovered device.</p>
-
+connection to the discovered device.</p> 
+ 
 <p>Once a connection is made with a remote device for the first time, a pairing
 request is automatically presented to the user. When a device is
 paired, the basic information about that device (such as the device name, class,
 and MAC address) is saved and can be read using the Bluetooth APIs. Using the
 known MAC address for a remote device, a connection can be initiated with it at
-any time without performing discovery (assuming the device is within range).</p>
-
+any time without performing discovery (assuming the device is within range).</p> 
+ 
 <p>Remember there is a difference between being paired and being connected. To
 be paired means that two devices are aware of each other's existence, have a
 shared link-key that can be used for authentication, and are capable of
@@ -265,28 +290,28 @@
 the devices currently share an RFCOMM channel and are able to transmit data with
 each other. The current Android Bluetooth API's require devices to be paired
 before an RFCOMM connection can be established. (Pairing is automatically performed
-when you initiate an encrypted connection with the Bluetooth APIs.)</p>
-
+when you initiate an encrypted connection with the Bluetooth APIs.)</p> 
+ 
 <p>The following sections describe how to find devices that have been paired, or
-discover new devices using device discovery.</p>
-
+discover new devices using device discovery.</p> 
+ 
 <p class="note"><strong>Note:</strong> Android-powered devices are not
 discoverable by default. A user can make
 the device discoverable for a limited time through the system settings, or an
 application can request that the user enable discoverability without leaving the
-application. How to <a href="#EnablingDiscoverability">enable discoverability</a>
-is discussed below.</p>
-
-
-<h3 id="QueryingPairedDevices">Querying paired devices</h3>
-
+application. How to <a href="#EnablingDiscoverability">enable discoverability</a> 
+is discussed below.</p> 
+ 
+ 
+<h3 id="QueryingPairedDevices">Querying paired devices</h3> 
+ 
 <p>Before performing device discovery, its worth querying the set
 of paired devices to see if the desired device is already known. To do so,
 call {@link android.bluetooth.BluetoothAdapter#getBondedDevices()}. This
 will return a Set of {@link android.bluetooth.BluetoothDevice}s representing
 paired devices. For example, you can query all paired devices and then
-show the name of each device to the user, using an ArrayAdapter:</p>
-<pre>
+show the name of each device to the user, using an ArrayAdapter:</p> 
+<pre> 
 Set&lt;BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
 // If there are paired devices
 if (pairedDevices.size() > 0) {
@@ -296,24 +321,24 @@
         mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
     }
 }
-</pre>
-
+</pre> 
+ 
 <p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
 in order to initiate a connection is the MAC address. In this example, it's saved
 as a part of an ArrayAdapter that's shown to the user. The MAC address can later
 be extracted in order to initiate the connection. You can learn more about creating
-a connection in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
-
-
-<h3 id="DiscoveringDevices">Discovering devices</h3>
-
+a connection in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p> 
+ 
+ 
+<h3 id="DiscoveringDevices">Discovering devices</h3> 
+ 
 <p>To start discovering devices, simply call {@link
 android.bluetooth.BluetoothAdapter#startDiscovery()}. The
 process is asynchronous and the method will immediately return with a boolean
 indicating whether discovery has successfully started. The discovery process
 usually involves an inquiry scan of about 12 seconds, followed by a page scan of
-each found device to retrieve its Bluetooth name.</p>
-
+each found device to retrieve its Bluetooth name.</p> 
+ 
 <p>Your application must register a BroadcastReceiver for the
 {@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent in
 order to receive information about each
@@ -324,8 +349,8 @@
 {@link android.bluetooth.BluetoothDevice#EXTRA_CLASS}, containing a
 {@link android.bluetooth.BluetoothDevice} and a {@link
 android.bluetooth.BluetoothClass}, respectively. For example, here's how you can
-register to handle the broadcast when devices are discovered:</p>
-<pre>
+register to handle the broadcast when devices are discovered:</p> 
+<pre> 
 // Create a BroadcastReceiver for ACTION_FOUND
 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
     public void onReceive(Context context, Intent intent) {
@@ -342,15 +367,15 @@
 // Register the BroadcastReceiver
 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
 registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
-</pre>
-
+</pre> 
+ 
 <p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
 in order to initiate a
 connection is the MAC address. In this example, it's saved as a part of an
 ArrayAdapter that's shown to the user. The MAC address can later be extracted in
 order to initiate the connection. You can learn more about creating a connection
-in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
-
+in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p> 
+ 
 <p class="caution"><strong>Caution:</strong> Performing device discovery is
 a heavy procedure for the Bluetooth
 adapter and will consume a lot of its resources. Once you have found a device to
@@ -359,41 +384,44 @@
 attempting a connection. Also, if you
 already hold a connection with a device, then performing discovery can
 significantly reduce the bandwidth available for the connection, so you should
-not perform discovery while connected.</p>
-
-<h4 id="EnablingDiscoverability">Enabling discoverability</h4>
-
+not perform discovery while connected.</p> 
+ 
+<h4 id="EnablingDiscoverability">Enabling discoverability</h4> 
+ 
 <p>If you would like to make the local device discoverable to other devices,
 call {@link android.app.Activity#startActivityForResult(Intent,int)} with the
-{@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action Intent.
-This will issue a request to enable discoverable mode through the system settings (without
-stopping your application). By default, the device will become discoverable for
-120 seconds. You can define a different duration by adding the
-{@link android.bluetooth.BluetoothAdapter#EXTRA_DISCOVERABLE_DURATION} Intent extra
-(maximum duration is 300 seconds). For example:</p>
-<pre>
-Intent discoverableIntent = new
+{@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action
+Intent. This will issue a request to enable discoverable mode through the system
+settings (without stopping your application). By default, the device will become
+discoverable for 120 seconds. You can define a different duration by adding the
+{@link android.bluetooth.BluetoothAdapter#EXTRA_DISCOVERABLE_DURATION} Intent
+extra. The maximum duration an app can set is 3600 seconds, and a value of 0
+means the device is always discoverable. Any value below 0 or above 3600 is
+automatically set to 120 secs). For example, this snippet sets the duration to
+300:</p> 
+
+<pre>Intent discoverableIntent = new
 Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
 discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
 startActivity(discoverableIntent);
-</pre>
-
-<div class="figure" style="width:200px">
-<img src="{@docRoot}images/bt_enable_discoverable.png" />
+</pre> 
+ 
+<div class="figure" style="width:200px"> 
+<img src="{@docRoot}images/bt_enable_discoverable.png" /> 
 <strong>Figure 2:</strong> The enabling discoverability dialog.
-</div>
-
+</div> 
+ 
 <p>A dialog will be displayed, requesting user permission to make the device
 discoverable, as shown in Figure 2. If the user responds "Yes," then the device
 will become discoverable for the specified amount of time. Your Activity will
 then receive a call to the {@link android.app.Activity#onActivityResult(int,int,Intent)
 onActivityResult())} callback, with the result code equal to the duration that the device
 is discoverable. If the user responded "No" or if an error occurred, the result code will
-be Activity.RESULT_CANCELLED.</p>
-
+be Activity.RESULT_CANCELLED.</p> 
+ 
 <p class="note"><strong>Note:</strong> If Bluetooth has not been enabled on the device,
-then enabling device discoverability will automatically enable Bluetooth.</p>
-
+then enabling device discoverability will automatically enable Bluetooth.</p> 
+ 
 <p>The device will silently remain in discoverable mode for the allotted time.
 If you would like to be notified when the discoverable mode has changed, you can
 register a BroadcastReceiver for the {@link
@@ -407,18 +435,18 @@
 android.bluetooth.BluetoothAdapter#SCAN_MODE_NONE},
 which indicate that the device is either in discoverable mode, not in
 discoverable mode but still able to receive connections, or not in discoverable
-mode and unable to receive connections, respectively.</p>
-
+mode and unable to receive connections, respectively.</p> 
+ 
 <p>You do not need to enable device discoverability if you will be initiating
 the connection to a remote device. Enabling discoverability is only necessary when
 you want your application to host a server socket that will accept incoming
 connections, because the remote devices must be able to discover the device
-before it can initiate the connection.</p>
-
-
-
-<h2 id="ConnectingDevices">Connecting Devices</h2>
-
+before it can initiate the connection.</p> 
+ 
+ 
+ 
+<h2 id="ConnectingDevices">Connecting Devices</h2> 
+ 
 <p>In order to create a connection between your application on two devices, you
 must implement both the server-side and client-side mechanisms, because one
 device must open a server socket and the other one must initiate the connection
@@ -428,36 +456,36 @@
 point, each device can obtain input and output streams and data transfer can
 begin, which is discussed in the section about <a
 href="#ManagingAConnection">Managing a Connection</a>. This section describes how
-to initiate the connection between two devices.</p>
-
+to initiate the connection between two devices.</p> 
+ 
 <p>The server device and the client device each obtain the required {@link
 android.bluetooth.BluetoothSocket} in different ways. The server will receive it
 when an incoming connection is accepted. The client will receive it when it
-opens an RFCOMM channel to the server.</p>
-
-<div class="figure" style="width:200px">
-<img src="{@docRoot}images/bt_pairing_request.png" />
+opens an RFCOMM channel to the server.</p> 
+ 
+<div class="figure" style="width:200px"> 
+<img src="{@docRoot}images/bt_pairing_request.png" /> 
 <strong>Figure 3:</strong> The Bluetooth pairing dialog.
-</div>
-
+</div> 
+ 
 <p>One implementation technique is to automatically prepare each device as a
 server, so that each one has a server socket open and listening for connections.
 Then either device can initiate a connection with the other and become the
 client. Alternatively, one device can explicitly "host" the connection and open
 a server socket on demand and the other device can simply initiate the
-connection.</p>
-
+connection.</p> 
+ 
 <p class="note"><strong>Note:</strong> If the two devices have not been previously paired,
 then the Android framework will automatically show a pairing request notification or
 dialog to the user during the connection procedure, as shown in Figure 3. So
 when attempting to connect devices,
 your application does not need to be concerned about whether or not the devices are
 paired. Your RFCOMM connection attempt will block until the user has successfully paired,
-or will fail if the user rejects pairing, or if pairing fails or times out. </p>
-
-
-<h3 id="ConnectingAsAServer">Connecting as a server</h3>
-
+or will fail if the user rejects pairing, or if pairing fails or times out. </p> 
+ 
+ 
+<h3 id="ConnectingAsAServer">Connecting as a server</h3> 
+ 
 <p>When you want to connect two devices, one must act as a server by holding an
 open {@link android.bluetooth.BluetoothServerSocket}. The purpose of the server
 socket is to listen for incoming connection requests and when one is accepted,
@@ -465,26 +493,26 @@
 android.bluetooth.BluetoothSocket} is acquired from the {@link
 android.bluetooth.BluetoothServerSocket},
 the {@link android.bluetooth.BluetoothServerSocket} can (and should) be
-discarded, unless you want to accept more connections.</p>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>About UUID</h2>
-
+discarded, unless you want to accept more connections.</p> 
+ 
+<div class="sidebox-wrapper"> 
+<div class="sidebox"> 
+<h2>About UUID</h2> 
+ 
 <p>A Universally Unique Identifier (UUID) is a standardized 128-bit format for a string
 ID used to uniquely identify information. The point of a UUID is that it's big
 enough that you can select any random and it won't clash. In this case, it's
 used to uniquely identify your application's Bluetooth service. To get a UUID to
 use with your application, you can use one of the many random UUID generators on
 the web, then initialize a {@link java.util.UUID} with {@link
-java.util.UUID#fromString(String)}.</p>
-</div>
-</div>
-
+java.util.UUID#fromString(String)}.</p> 
+</div> 
+</div> 
+ 
 <p>Here's the basic procedure to set up a server socket and accept a
-connection:</p>
-
-<ol>
+connection:</p> 
+ 
+<ol> 
 <li>Get a {@link android.bluetooth.BluetoothServerSocket} by calling the
 {@link
 android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
@@ -496,9 +524,9 @@
 agreement with the client device. That is, when the client attempts to connect
 with this device, it will carry a UUID that uniquely identifies the service with
 which it wants to connect. These UUIDs must match in order for the connection to
-be accepted (in the next step).</p>
-</li>
-
+be accepted (in the next step).</p> 
+</li> 
+ 
 <li>Start listening for connection requests by calling
 {@link android.bluetooth.BluetoothServerSocket#accept()}.
 <p>This is a blocking call. It will return when either a connection has been
@@ -506,9 +534,9 @@
 remote device has sent a connection request with a UUID matching the one
 registered with this listening server socket. When successful, {@link
 android.bluetooth.BluetoothServerSocket#accept()} will
-return a connected {@link android.bluetooth.BluetoothSocket}.</p>
-</li>
-
+return a connected {@link android.bluetooth.BluetoothSocket}.</p> 
+</li> 
+ 
 <li>Unless you want to accept additional connections, call
 {@link android.bluetooth.BluetoothServerSocket#close()}.
 <p>This releases the server socket and all its resources, but does <em>not</em> close the
@@ -517,10 +545,10 @@
 connected client per channel at a time, so in most cases it makes sense to call {@link
 android.bluetooth.BluetoothServerSocket#close()} on the {@link
 android.bluetooth.BluetoothServerSocket} immediately after accepting a connected
-socket.</p>
-</li>
-</ol>
-
+socket.</p> 
+</li> 
+</ol> 
+ 
 <p>The {@link android.bluetooth.BluetoothServerSocket#accept()} call should not
 be executed in the main Activity UI thread because it is a blocking call and
 will prevent any other interaction with the application. It usually makes
@@ -533,16 +561,16 @@
 android.bluetooth.BluetoothSocket}) from another thread and the blocked call will
 immediately return. Note that all methods on a {@link
 android.bluetooth.BluetoothServerSocket} or {@link android.bluetooth.BluetoothSocket}
-are thread-safe.</p>
-
-<h4>Example</h4>
-
+are thread-safe.</p> 
+ 
+<h4>Example</h4> 
+ 
 <p>Here's a simplified thread for the server component that accepts incoming
-connections:</p>
-<pre>
+connections:</p> 
+<pre> 
 private class AcceptThread extends Thread {
     private final BluetoothServerSocket mmServerSocket;
-
+ 
     public AcceptThread() {
         // Use a temporary object that is later assigned to mmServerSocket,
         // because mmServerSocket is final
@@ -553,7 +581,7 @@
         } catch (IOException e) { }
         mmServerSocket = tmp;
     }
-
+ 
     public void run() {
         BluetoothSocket socket = null;
         // Keep listening until exception occurs or a socket is returned
@@ -572,7 +600,7 @@
             }
         }
     }
-
+ 
     /** Will cancel the listening socket, and cause the thread to finish */
     public void cancel() {
         try {
@@ -580,37 +608,37 @@
         } catch (IOException e) { }
     }
 }
-</pre>
-
+</pre> 
+ 
 <p>In this example, only one incoming connection is desired, so as soon as a
 connection is accepted and the {@link android.bluetooth.BluetoothSocket} is
 acquired, the application
 sends the acquired {@link android.bluetooth.BluetoothSocket} to a separate
 thread, closes the
-{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.</p>
-
+{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.</p> 
+ 
 <p>Note that when {@link android.bluetooth.BluetoothServerSocket#accept()}
 returns the {@link android.bluetooth.BluetoothSocket}, the socket is already
 connected, so you should <em>not</em> call {@link
 android.bluetooth.BluetoothSocket#connect()} (as you do from the
-client-side).</p>
-
+client-side).</p> 
+ 
 <p><code>manageConnectedSocket()</code> is a fictional method in the application
 that will
 initiate the thread for transferring data, which is discussed in the section
-about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
-
+about <a href="#ManagingAConnection">Managing a Connection</a>.</p> 
+ 
 <p>You should usually close your {@link android.bluetooth.BluetoothServerSocket}
 as soon as you are done listening for incoming connections. In this example, {@link
 android.bluetooth.BluetoothServerSocket#close()} is called as soon
 as the {@link android.bluetooth.BluetoothSocket} is acquired. You may also want
 to provide a public method in your thread that can close the private {@link
 android.bluetooth.BluetoothSocket} in the event that you need to stop listening on the
-server socket.</p>
-
-
-<h3 id="ConnectingAsAClient">Connecting as a client</h3>
-
+server socket.</p> 
+ 
+ 
+<h3 id="ConnectingAsAClient">Connecting as a client</h3> 
+ 
 <p>In order to initiate a connection with a remote device (a device holding an
 open
 server socket), you must first obtain a {@link
@@ -619,11 +647,11 @@
 section about <a
 href="#FindingDevices">Finding Devices</a>.) You must then use the
 {@link android.bluetooth.BluetoothDevice} to acquire a {@link
-android.bluetooth.BluetoothSocket} and initiate the connection.</p>
-
-<p>Here's the basic procedure:</p>
-
-<ol>
+android.bluetooth.BluetoothSocket} and initiate the connection.</p> 
+ 
+<p>Here's the basic procedure:</p> 
+ 
+<ol> 
 <li>Using the {@link android.bluetooth.BluetoothDevice}, get a {@link
 android.bluetooth.BluetoothSocket} by calling {@link
 android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(UUID)}.
@@ -634,9 +662,9 @@
 android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
 UUID)}). Using the same UUID is simply a matter of hard-coding the UUID string
 into your application and then referencing it from both the server and client
-code.</p>
-</li>
-
+code.</p> 
+</li> 
+ 
 <li>Initiate the connection by calling {@link
 android.bluetooth.BluetoothSocket#connect()}.
 <p>Upon this call, the system will perform an SDP lookup on the remote device in
@@ -647,34 +675,34 @@
 blocking call. If, for
 any reason, the connection fails or the {@link
 android.bluetooth.BluetoothSocket#connect()} method times out (after about
-12 seconds), then it will throw an exception.</p>
+12 seconds), then it will throw an exception.</p> 
 <p>Because {@link
 android.bluetooth.BluetoothSocket#connect()} is a blocking call, this connection
 procedure should always be performed in a thread separate from the main Activity
-thread.</p>
+thread.</p> 
 <p class="note">Note: You should always ensure that the device is not performing
 device discovery when you call {@link
 android.bluetooth.BluetoothSocket#connect()}. If discovery is in progress, then
 the
-connection attempt will be significantly slowed and is more likely to fail.</p>
-</li>
-</ol>
-
-<h4>Example</h4>
-
+connection attempt will be significantly slowed and is more likely to fail.</p> 
+</li> 
+</ol> 
+ 
+<h4>Example</h4> 
+ 
 <p>Here is a basic example of a thread that initiates a Bluetooth
-connection:</p>
-<pre>
+connection:</p> 
+<pre> 
 private class ConnectThread extends Thread {
     private final BluetoothSocket mmSocket;
     private final BluetoothDevice mmDevice;
-
+ 
     public ConnectThread(BluetoothDevice device) {
         // Use a temporary object that is later assigned to mmSocket,
         // because mmSocket is final
         BluetoothSocket tmp = null;
         mmDevice = device;
-
+ 
         // Get a BluetoothSocket to connect with the given BluetoothDevice
         try {
             // MY_UUID is the app's UUID string, also used by the server code
@@ -682,11 +710,11 @@
         } catch (IOException e) { }
         mmSocket = tmp;
     }
-
+ 
     public void run() {
         // Cancel discovery because it will slow down the connection
         mBluetoothAdapter.cancelDiscovery();
-
+ 
         try {
             // Connect the device through the socket. This will block
             // until it succeeds or throws an exception
@@ -698,11 +726,11 @@
             } catch (IOException closeException) { }
             return;
         }
-
+ 
         // Do work to manage the connection (in a separate thread)
         manageConnectedSocket(mmSocket);
     }
-
+ 
     /** Will cancel an in-progress connection, and close the socket */
     public void cancel() {
         try {
@@ -710,42 +738,42 @@
         } catch (IOException e) { }
     }
 }
-</pre>
-
+</pre> 
+ 
 <p>Notice that {@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} is called
 before the connection is made. You should always do this before connecting and it is safe
 to call without actually checking whether it is running or not (but if you do want to
-check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).</p>
-
+check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).</p> 
+ 
 <p><code>manageConnectedSocket()</code> is a fictional method in the application
 that will initiate the thread for transferring data, which is discussed in the section
-about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
-
+about <a href="#ManagingAConnection">Managing a Connection</a>.</p> 
+ 
 <p>When you're done with your {@link android.bluetooth.BluetoothSocket}, always
 call {@link android.bluetooth.BluetoothSocket#close()} to clean up.
 Doing so will immediately close the connected socket and clean up all internal
-resources.</p>
-
-
-<h2 id="ManagingAConnection">Managing a Connection</h2>
-
+resources.</p> 
+ 
+ 
+<h2 id="ManagingAConnection">Managing a Connection</h2> 
+ 
 <p>When you have successfully connected two (or more) devices, each one will
 have a connected {@link android.bluetooth.BluetoothSocket}. This is where the fun
 begins because you can share data between devices. Using the {@link
 android.bluetooth.BluetoothSocket}, the general procedure to transfer arbitrary data is
-simple:</p>
-<ol>
+simple:</p> 
+<ol> 
 <li>Get the {@link java.io.InputStream} and {@link java.io.OutputStream} that
 handle transmissions through the socket, via {@link
 android.bluetooth.BluetoothSocket#getInputStream()} and
-{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.</li>
-
+{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.</li> 
+ 
 <li>Read and write data to the streams with {@link
-java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.</li>
-</ol>
-
-<p>That's it.</p>
-
+java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.</li> 
+</ol> 
+ 
+<p>That's it.</p> 
+ 
 <p>There are, of course, implementation details to consider. First and foremost,
 you should use a dedicated thread for all stream reading and writing. This is
 important because both {@link java.io.InputStream#read(byte[])} and {@link
@@ -756,37 +784,37 @@
 java.io.InputStream#read(byte[])} quickly enough and the intermediate buffers are full.
 So, your main loop in the thread should be dedicated to reading from the {@link
 java.io.InputStream}. A separate public method in the thread can be used to initiate
-writes to the {@link java.io.OutputStream}.</p>
-
-<h4>Example</h4>
-
-<p>Here's an example of how this might look:</p>
-<pre>
+writes to the {@link java.io.OutputStream}.</p> 
+ 
+<h4>Example</h4> 
+ 
+<p>Here's an example of how this might look:</p> 
+<pre> 
 private class ConnectedThread extends Thread {
     private final BluetoothSocket mmSocket;
     private final InputStream mmInStream;
     private final OutputStream mmOutStream;
-
+ 
     public ConnectedThread(BluetoothSocket socket) {
         mmSocket = socket;
         InputStream tmpIn = null;
         OutputStream tmpOut = null;
-
+ 
         // Get the input and output streams, using temp objects because
         // member streams are final
         try {
             tmpIn = socket.getInputStream();
             tmpOut = socket.getOutputStream();
         } catch (IOException e) { }
-
+ 
         mmInStream = tmpIn;
         mmOutStream = tmpOut;
     }
-
+ 
     public void run() {
         byte[] buffer = new byte[1024];  // buffer store for the stream
         int bytes; // bytes returned from read()
-
+ 
         // Keep listening to the InputStream until an exception occurs
         while (true) {
             try {
@@ -800,14 +828,14 @@
             }
         }
     }
-
+ 
     /* Call this from the main Activity to send data to the remote device */
     public void write(byte[] bytes) {
         try {
             mmOutStream.write(bytes);
         } catch (IOException e) { }
     }
-
+ 
     /* Call this from the main Activity to shutdown the connection */
     public void cancel() {
         try {
@@ -815,27 +843,124 @@
         } catch (IOException e) { }
     }
 }
-</pre>
-
+</pre> 
+ 
 <p>The constructor acquires the necessary streams and once executed, the thread
 will wait for data to come through the InputStream. When {@link
 java.io.InputStream#read(byte[])} returns with
 bytes from the stream, the data is sent to the main Activity using a member
 Handler from the parent class. Then it goes back and waits for more bytes from
-the stream.</p>
-
+the stream.</p> 
+ 
 <p>Sending outgoing data is as simple as calling the thread's
 <code>write()</code> method from the main Activity and passing in the bytes to
 be sent. This method then simply calls {@link
-java.io.OutputStream#write(byte[])} to send the data to the remote device.</p>
-
+java.io.OutputStream#write(byte[])} to send the data to the remote device.</p> 
+ 
 <p>The thread's <code>cancel()</code> method is important so that the connection
 can be
 terminated at any time by closing the {@link android.bluetooth.BluetoothSocket}.
 This should always be called when you're done using the Bluetooth
-connection.</p>
+connection.</p> 
+ 
+<div class="special"> 
+<p>For a  demonstration of using the Bluetooth APIs, see the <a
+href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app</a>.</p> 
+</div> 
 
-<div class="special">
-<p>For a complete demonstration using the Bluetooth APIs, see the <a
-href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app</a>.</p>
-</div>
+<h2 id="Profiles">Working with Profiles</h2> 
+
+<p>Starting in Android 3.0, the Bluetooth API includes support for working with
+Bluetooth profiles. A <em>Bluetooth profile</em> is a wireless interface
+specification for Bluetooth-based communication between devices. An example
+is the Hands-Free profile. For a mobile phone to connect to a wireless headset,
+both devices must support the Hands-Free profile. </p> 
+
+<p>You can implement the interface {@link android.bluetooth.BluetoothProfile} to write
+your own classes to support a particular Bluetooth profile. The Android
+Bluetooth API provides implementations for the following Bluetooth
+profiles:</p> 
+<ul> 
+
+  <li><strong>Headset</strong>. The Headset profile provides support for
+Bluetooth headsets to be used with mobile phones. Android provides the {@link
+android.bluetooth.BluetoothHeadset} class, which is a proxy for controlling the
+Bluetooth Headset Service via interprocess communication (<a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#IPC">IPC</a
+>). This includes both  Bluetooth Headset and Hands-Free (v1.5) profiles. The
+{@link android.bluetooth.BluetoothHeadset} class includes support for AT commands.
+For more discussion of this topic, see <a href="#AT-Commands">Vendor-specific AT commands</a></li> 
+
+  <li><strong>A2DP</strong>. The Advanced Audio Distribution Profile (A2DP)
+profile defines how high quality audio can be streamed from one device to
+another over a Bluetooth connection. Android provides the {@link
+android.bluetooth.BluetoothA2dp} class, which is a proxy for controlling
+the Bluetooth A2DP  Service via IPC.</li> 
+
+</ul> 
+
+<p>Here are the basic steps for working with a profile:</p> 
+<ol> 
+
+  <li>Get the default adapter, as described in <a href="{@docRoot}guide/topics/wireless/bluetooth.
+html#SettingUp">Setting Up Bluetooth</a>.</li> 
+
+  <li>Use {@link
+android.bluetooth.BluetoothAdapter#getProfileProxy(android.content.Context,
+android.bluetooth.BluetoothProfile.ServiceListener, int) getProfileProxy()} to
+establish a connection to the profile proxy object associated with the profile.
+In the example below, the profile proxy object is an instance of {@link
+android.bluetooth.BluetoothHeadset}. </li> 
+
+  <li>Set up a  {@link android.bluetooth.BluetoothProfile.ServiceListener}. This
+listener notifies {@link android.bluetooth.BluetoothProfile} IPC clients when
+they have been connected to or disconnected from the service.</li> 
+
+  <li>In {@link
+android.bluetooth.BluetoothProfile.ServiceListener#onServiceConnected(int,
+android.bluetooth.BluetoothProfile) onServiceConnected()}, get a handle
+to the profile proxy object.</li> 
+
+  <li>Once you have the profile proxy object, you can use it to monitor the
+state of the connection and perform other operations that are relevant to that
+profile.</li> 
+</ol> 
+<p> For example, this code snippet shows how to connect to a {@link android.bluetooth.BluetoothHeadset} proxy object so that you can control the
+Headset profile:</p> 
+
+<pre>BluetoothHeadset mBluetoothHeadset;
+ 
+// Get the default adapter
+BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ 
+// Establish connection to the proxy.
+mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
+ 
+private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
+    public void onServiceConnected(int profile, BluetoothProfile proxy) {
+        if (profile == BluetoothProfile.HEADSET) {
+            mBluetoothHeadset = (BluetoothHeadset) proxy;
+        }
+    }
+    public void onServiceDisconnected(int profile) {
+        if (profile == BluetoothProfile.HEADSET) {
+            mBluetoothHeadset = null;
+        }
+    }
+};
+ 
+// ... call functions on mBluetoothHeadset
+ 
+// Close proxy connection after use.
+mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
+</pre> 
+
+<h3 id="AT-Commands">Vendor-specific AT commands</h3> 
+
+<p>Starting in Android 3.0, applications can register to receive system
+broadcasts of pre-defined vendor-specific AT commands sent by headsets (such as
+a Plantronics +XEVENT command). For example, an application could receive
+broadcasts that indicate a connected device's battery level and could notify the
+user or take other action as needed. Create a broadcast receiver for the {@link
+android.bluetooth.BluetoothHeadset#ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intent
+to handle vendor-specific AT commands for the headset.</p>
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index 097d004..e8c9ae7 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -547,6 +547,16 @@
     }
   },
   {
+    tags: ['sample', 'new', 'media' ],
+    path: 'samples/RandomMusicPlayer/index.html',
+    title: {
+      en: 'Random Music Player'
+    },
+    description: {
+      en: 'Demonstrates how to write a multimedia application that plays music from the device and from URLs. It manages media playback from a service and can play music in the background, respecting audio focus changes.'
+    }
+  },
+  {
     tags: ['sample', 'new', 'newfeature', 'performance', 'gamedev', 'gl'],
     path: 'samples/RenderScript/index.html',
     title: {
diff --git a/docs/html/resources/samples/images/randommusicplayer.png b/docs/html/resources/samples/images/randommusicplayer.png
new file mode 100644
index 0000000..e16e067
--- /dev/null
+++ b/docs/html/resources/samples/images/randommusicplayer.png
Binary files differ
diff --git a/docs/html/resources/tutorials/views/hello-spinner.jd b/docs/html/resources/tutorials/views/hello-spinner.jd
index 7a3a9c3..e9dc20f 100644
--- a/docs/html/resources/tutorials/views/hello-spinner.jd
+++ b/docs/html/resources/tutorials/views/hello-spinner.jd
@@ -105,7 +105,7 @@
 
     public void onItemSelected(AdapterView&lt;?> parent,
         View view, int pos, long id) {
-      Toast.makeText(parent.getContext()), "The planet is " +
+      Toast.makeText(parent.getContext(), "The planet is " +
           parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
     }
 
diff --git a/docs/html/sdk/android-3.1-highlights.jd b/docs/html/sdk/android-3.1-highlights.jd
index 3d132a3..88bc1ee 100644
--- a/docs/html/sdk/android-3.1-highlights.jd
+++ b/docs/html/sdk/android-3.1-highlights.jd
@@ -143,8 +143,8 @@
 <p>To make the platform even better for gaming, Android 3.1 adds support for
 most PC joysticks and gamepads that are connected over USB or Bluetooth HID.</p>
 
-<p>For example, users can connect Sony Playstation&trade; 3 and XBox 360&trade; game
-controllers over USB (but not Bluetooth), Logitech Dual Action&trade; gamepads and
+<p>For example, users can connect PlayStation<sup>&reg;</sup>3 and Xbox 360<sup>&reg;</sup>
+game controllers over USB (but not Bluetooth), Logitech Dual Action&trade; gamepads and
 flight sticks, or a car racing controller. Game controllers that use proprietary
 networking or pairing are not supported by default, but in general, the platform
 supports most PC-connectible joysticks and gamepads.</p>
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index 27e742a..3c2ba8b 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -80,6 +80,12 @@
     <td><a href="http://www.kyocera-wireless.com/support/phone_drivers.htm">http://www.kyocera-wireless.com/support/phone_drivers.htm</a>
     </td>
   </tr>
+  <tr>
+    <td>Lenevo</td>
+    <td><a href="http://developer.lenovomm.com/developer/download.jsp"
+        >http://developer.lenovomm.com/developer/download.jsp</a>
+    </td>
+  </tr>
   <tr><td>LGE</td>	<td><a
 href="http://www.lg.com/us/mobile-phones/mobile-support/mobile-lg-mobile-phone-support.jsp">http://www.lg.com/us/mobile-phones/mobile-support/mobile-lg-mobile-phone-support.jsp</a></td>
 </tr><tr><td>Motorola</td>	<td><a
diff --git a/docs/html/search.jd b/docs/html/search.jd
index 609ade9..339ce2d 100644
--- a/docs/html/search.jd
+++ b/docs/html/search.jd
@@ -1,144 +1,140 @@
 page.title=Search Results

 @jd:body

 

-<script src="http://www.google.com/jsapi" type="text/javascript"></script>
+<script src="http://www.google.com/jsapi" type="text/javascript"></script>

 <script src="{@docRoot}assets/jquery-history.js" type="text/javascript"></script>

-<script type="text/javascript">      
-      var tabIndex = 0;
-            
-      google.load('search', '1');
-
-      function OnLoad() {
-        document.getElementById("search_autocomplete").style.color = "#000";
-
-        // create search control
-        searchControl = new google.search.SearchControl();
-
-        // use our existing search form and use tabs when multiple searchers are used
-        drawOptions = new google.search.DrawOptions();
-        drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED);
-        drawOptions.setInput(document.getElementById("search_autocomplete"));
-
-        // configure search result options
-        searchOptions = new google.search.SearcherOptions();
-        searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
-
-        // configure each of the searchers, for each tab
-        devSiteSearcher = new google.search.WebSearch();
-        devSiteSearcher.setUserDefinedLabel("All Developers Site");
-        devSiteSearcher.setSiteRestriction("http://developer.android.com/");
-
-        devGuideSearcher = new google.search.WebSearch();
-        devGuideSearcher.setUserDefinedLabel("Dev Guide");
-        devGuideSearcher.setSiteRestriction("http://developer.android.com/guide/");
-
-        referenceSearcher = new google.search.WebSearch();
-        referenceSearcher.setUserDefinedLabel("Reference");
-        referenceSearcher.setSiteRestriction("http://developer.android.com/reference/");
-
-        blogSearcher = new google.search.WebSearch();
-        blogSearcher.setUserDefinedLabel("Blog");
-        blogSearcher.setSiteRestriction("http://android-developers.blogspot.com");
-
-        groupsSearcher = new google.search.WebSearch();
-        groupsSearcher.setUserDefinedLabel("Developer Groups");
-        groupsSearcher.setSiteRestriction("001283715400630100512:ggqrtvkztwm");
-
-        sourceSiteSearcher = new google.search.WebSearch();
-        sourceSiteSearcher.setUserDefinedLabel("Android Source");
-        sourceSiteSearcher.setSiteRestriction("http://source.android.com");
-
-        homeSiteSearcher = new google.search.WebSearch();
-        homeSiteSearcher.setUserDefinedLabel("Android Home");
-        homeSiteSearcher.setSiteRestriction("http://www.android.com");
- 
-        // add each searcher to the search control
-        searchControl.addSearcher(devSiteSearcher, searchOptions);
-        searchControl.addSearcher(devGuideSearcher, searchOptions);
-        searchControl.addSearcher(referenceSearcher, searchOptions);
-        searchControl.addSearcher(groupsSearcher, searchOptions);
-        searchControl.addSearcher(sourceSiteSearcher, searchOptions);
-        searchControl.addSearcher(blogSearcher, searchOptions);
-
-        // configure result options
-        searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
-        searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);
-        searchControl.setTimeoutInterval(google.search.SearchControl.TIMEOUT_LONG);
-        searchControl.setNoResultsString(google.search.SearchControl.NO_RESULTS_DEFAULT_STRING);
-
-        // upon ajax search, refresh the url and search title
-        searchControl.setSearchStartingCallback(this, function(control, searcher, query) {
-            // save the tab index from the hash
-            tabIndex = location.hash.split("&t=")[1];
-
-            $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
-            $.history.add('q=' + query + '&t=' + tabIndex);
-            openTab();
-        });
-
-        // draw the search results box
-        searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);
-
-        // get query and execute the search
-        if (location.hash.indexOf("&t=") != -1) {
-          searchControl.execute(decodeURI(getQuery(location.hash)));
-        }
-        
-        document.getElementById("search_autocomplete").focus();
-        addTabListeners();
-      }
-      // End of OnLoad
-
-
-      google.setOnLoadCallback(OnLoad, true);
-
-      // when an event on the browser history occurs (back, forward, load) perform a search
-      $(window).history(function(e, hash) {
-        var query = decodeURI(getQuery(hash));
-        searchControl.execute(query);
-
-        $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
-      });
-
-      // forcefully regain key-up event control (previously jacked by search api)
-      $("#search_autocomplete").keyup(function(event) {
-        return search_changed(event, false, '/');
-      });
-
-      // open a tab, specified by its array position
-      function openTab() {
-        tabIndex = location.hash.split("&t=")[1];
-        
-        // show the appropriate tab
-        var tabHeaders = $(".gsc-tabHeader");
-        $(tabHeaders[tabIndex]).click();
-      }
-      
-      // add event listeners to each tab so we can track the browser history
-      function addTabListeners() {
-        var tabHeaders = $(".gsc-tabHeader");
-        for (var i = 0; i < tabHeaders.length; i++) {
-          $(tabHeaders[i]).attr("id",i).click(function() {
-            var tabHeaders = $(".gsc-tabHeader");
+<script type="text/javascript">      

+      var tabIndex = 0;

+            

+      google.load('search', '1');

+

+      function OnLoad() {

+        document.getElementById("search_autocomplete").style.color = "#000";

+

+        // create search control

+        searchControl = new google.search.SearchControl();

+

+        // use our existing search form and use tabs when multiple searchers are used

+        drawOptions = new google.search.DrawOptions();

+        drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED);

+        drawOptions.setInput(document.getElementById("search_autocomplete"));

+

+        // configure search result options

+        searchOptions = new google.search.SearcherOptions();

+        searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);

+

+        // configure each of the searchers, for each tab

+        devSiteSearcher = new google.search.WebSearch();

+        devSiteSearcher.setUserDefinedLabel("All");

+        devSiteSearcher.setSiteRestriction("001482626316274216503:zu90b7s047u");

+

+        devGuideSearcher = new google.search.WebSearch();

+        devGuideSearcher.setUserDefinedLabel("Dev Guide");

+        devGuideSearcher.setSiteRestriction("http://developer.android.com/guide/");

+

+        referenceSearcher = new google.search.WebSearch();

+        referenceSearcher.setUserDefinedLabel("Reference");

+        referenceSearcher.setSiteRestriction("http://developer.android.com/reference/");

+

+        blogSearcher = new google.search.WebSearch();

+        blogSearcher.setUserDefinedLabel("Blog");

+        blogSearcher.setSiteRestriction("http://android-developers.blogspot.com");

+

+        groupsSearcher = new google.search.WebSearch();

+        groupsSearcher.setUserDefinedLabel("Developer Groups");

+        groupsSearcher.setSiteRestriction("001283715400630100512:ggqrtvkztwm");

+

+        sourceSiteSearcher = new google.search.WebSearch();

+        sourceSiteSearcher.setUserDefinedLabel("Android Source");

+        sourceSiteSearcher.setSiteRestriction("http://source.android.com");

+ 

+        // add each searcher to the search control

+        searchControl.addSearcher(devSiteSearcher, searchOptions);

+        searchControl.addSearcher(devGuideSearcher, searchOptions);

+        searchControl.addSearcher(referenceSearcher, searchOptions);

+        searchControl.addSearcher(groupsSearcher, searchOptions);

+        searchControl.addSearcher(sourceSiteSearcher, searchOptions);

+        searchControl.addSearcher(blogSearcher, searchOptions);

+

+        // configure result options

+        searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);

+        searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);

+        searchControl.setTimeoutInterval(google.search.SearchControl.TIMEOUT_LONG);

+        searchControl.setNoResultsString(google.search.SearchControl.NO_RESULTS_DEFAULT_STRING);

+

+        // upon ajax search, refresh the url and search title

+        searchControl.setSearchStartingCallback(this, function(control, searcher, query) {

+            // save the tab index from the hash

+            tabIndex = location.hash.split("&t=")[1];

+

+            $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");

+            $.history.add('q=' + query + '&t=' + tabIndex);

+            openTab();

+        });

+

+        // draw the search results box

+        searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);

+

+        // get query and execute the search

+        if (location.hash.indexOf("&t=") != -1) {

+          searchControl.execute(decodeURI(getQuery(location.hash)));

+        }

+

+        document.getElementById("search_autocomplete").focus();

+        addTabListeners();

+      }

+      // End of OnLoad

+

+

+      google.setOnLoadCallback(OnLoad, true);

+

+      // when an event on the browser history occurs (back, forward, load) perform a search

+      $(window).history(function(e, hash) {

+        var query = decodeURI(getQuery(hash));

+        searchControl.execute(query);

+

+        $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");

+      });

+

+      // forcefully regain key-up event control (previously jacked by search api)

+      $("#search_autocomplete").keyup(function(event) {

+        return search_changed(event, false, '/');

+      });

+

+      // open a tab, specified by its array position

+      function openTab() {

+        tabIndex = location.hash.split("&t=")[1];

+

+        // show the appropriate tab

+        var tabHeaders = $(".gsc-tabHeader");

+        $(tabHeaders[tabIndex]).click();

+      }

+

+      // add event listeners to each tab so we can track the browser history

+      function addTabListeners() {

+        var tabHeaders = $(".gsc-tabHeader");

+        for (var i = 0; i < tabHeaders.length; i++) {

+          $(tabHeaders[i]).attr("id",i).click(function() {

+            var tabHeaders = $(".gsc-tabHeader");

             var tabIndex = $(this).attr("id");

-            $.history.add('q=' + getQuery(location.hash) + '&t=' + tabIndex); // update the hash with the new tab
-          });
-        }
-      }
-      
+            $.history.add('q=' + getQuery(location.hash) + '&t=' + tabIndex); // update the hash with the new tab

+          });

+        }

+      }

+

       function getQuery(hash) {

-        var hashParts = hash.split('&t=');
-        var queryParts = hashParts[0].split('=');
-        return queryParts[1];
-      }
-
-      /* returns the given string with all HTML brackets converted to entities
-         TODO: move this to the site's JS library */
-      function escapeHTML(string) {
-        return string.replace(/</g,"&lt;")
-                     .replace(/>/g,"&gt;");
-      }
-
+        var hashParts = hash.split('&t=');

+        var queryParts = hashParts[0].split('=');

+        return queryParts[1];

+      }

+

+      /* returns the given string with all HTML brackets converted to entities

+         TODO: move this to the site's JS library */

+      function escapeHTML(string) {

+        return string.replace(/</g,"&lt;")

+                     .replace(/>/g,"&gt;");

+      }

+

 </script>

 

   <div id="mainBodyFixed" style="width:auto; margin:20px">

diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index 3dee435..5400bdd 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -43,6 +43,10 @@
 }
 
 bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const {
+    if (String8("") == mimeType) {
+        return false;
+    }
+
     for (unsigned int i = 0; i < mMimeTypeVector.size(); i++) {
         const String8 item = mMimeTypeVector.itemAt(i);
 
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 458f1b6..2d8e877 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -107,6 +107,7 @@
         handle->decryptInfo = NULL;
     }
     handle->copyControlVector.clear();
+    handle->extendedData.clear();
 }
 
 int BpDrmManagerService::addUniqueId(int uniqueId) {
diff --git a/drm/java/android/drm/DrmRights.java b/drm/java/android/drm/DrmRights.java
index 5907956..ef9c21d 100755
--- a/drm/java/android/drm/DrmRights.java
+++ b/drm/java/android/drm/DrmRights.java
@@ -107,31 +107,24 @@
 
     /**
      * Creates a <code>DrmRights</code> object with the given parameters.
-     *<p>
-     * The application can pass the processed data as a <code>String</code> or as binary data.
-     *<p>
-     * The following code snippet shows how to pass the processed data as a <code>String</code>:
-     *<p>
-     * new DrmRights(data.getBytes(), mimeType)
-     *<p>
-     * The following code snippet shows how to pass the processed data as binary data:
-     *<p>
-     * new DrmRights(binaryData[], mimeType)
      *
-     * @param data A {@link ProcessedData} object.
+     * @param data A {@link ProcessedData} object containing rights information.
+     *             data could be null because it's optional for some DRM schemes.
      * @param mimeType The MIME type.
      */
     public DrmRights(ProcessedData data, String mimeType) {
-        mData = data.getData();
+        if (data != null) {
+            mData = data.getData();
 
-        String accountId = data.getAccountId();
-        if (null != accountId && !accountId.equals("")) {
-            mAccountId = accountId;
-        }
+            String accountId = data.getAccountId();
+            if (null != accountId && !accountId.equals("")) {
+                mAccountId = accountId;
+            }
 
-        String subscriptionId = data.getSubscriptionId();
-        if (null != subscriptionId && !subscriptionId.equals("")) {
-            mSubscriptionId = subscriptionId;
+            String subscriptionId = data.getSubscriptionId();
+            if (null != subscriptionId && !subscriptionId.equals("")) {
+                mSubscriptionId = subscriptionId;
+            }
         }
 
         mMimeType = mimeType;
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index a57dd98..a36bd4a 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -145,7 +145,6 @@
 
 status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
             const String8& rightsPath, const String8& contentPath) {
-    status_t status = DRM_ERROR_UNKNOWN;
     return getDrmManagerService()->saveRights(
                 uniqueId, drmRights, rightsPath, contentPath);
 }
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 12dc93c..40d54bb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -681,7 +681,8 @@
      */
     public enum CompressFormat {
         JPEG    (0),
-        PNG     (1);
+        PNG     (1),
+        WEBP    (2);
 
         CompressFormat(int nativeInt) {
             this.nativeInt = nativeInt;
diff --git a/graphics/java/android/graphics/ParcelSurfaceTexture.java b/graphics/java/android/graphics/ParcelSurfaceTexture.java
index 5272cc6..cc8bd02 100644
--- a/graphics/java/android/graphics/ParcelSurfaceTexture.java
+++ b/graphics/java/android/graphics/ParcelSurfaceTexture.java
@@ -19,6 +19,7 @@
 import android.graphics.SurfaceTexture;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.view.Surface;
 
 /**
  *
@@ -34,6 +35,17 @@
     private int mISurfaceTexture;
 
     /**
+     * Create a new ParcelSurfaceTexture from a Surface
+     *
+     * @param surface The Surface to create a ParcelSurfaceTexture from.
+     *
+     * @return Returns a new ParcelSurfaceTexture for the given Surface.
+     */
+    public static ParcelSurfaceTexture fromSurface(Surface surface) {
+        return new ParcelSurfaceTexture(surface);
+    }
+
+    /**
      * Create a new ParcelSurfaceTexture from a SurfaceTexture
      *
      * @param surfaceTexture The SurfaceTexture to transport.
@@ -75,8 +87,11 @@
     private ParcelSurfaceTexture(Parcel in) {
         nativeReadFromParcel(in);
     }
+    private ParcelSurfaceTexture(Surface surface) {
+        nativeInitFromSurface(surface);
+    }
     private ParcelSurfaceTexture(SurfaceTexture surfaceTexture) {
-        nativeInit(surfaceTexture);
+        nativeInitFromSurfaceTexture(surfaceTexture);
     }
 
     @Override
@@ -88,7 +103,8 @@
         }
     }
 
-    private native void nativeInit(SurfaceTexture surfaceTexture);
+    private native void nativeInitFromSurface(Surface surface);
+    private native void nativeInitFromSurfaceTexture(SurfaceTexture surfaceTexture);
     private native void nativeFinalize();
     private native void nativeWriteToParcel(Parcel dest, int flags);
     private native void nativeReadFromParcel(Parcel in);
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 6c7341f..90a7ac2 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -93,6 +93,19 @@
      * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
      */
     public SurfaceTexture(int texName) {
+        this(texName, true);
+    }
+
+    /**
+     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
+     *
+     * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
+     * @param allowSynchronousMode whether the SurfaceTexture can run in the synchronous mode.
+     *      When the image stream comes from OpenGL, SurfaceTexture may run in the synchronous
+     *      mode where the producer side may be blocked to avoid skipping frames. To avoid the
+     *      thread block, set allowSynchronousMode to false.
+     */
+    public SurfaceTexture(int texName, boolean allowSynchronousMode) {
         Looper looper;
         if ((looper = Looper.myLooper()) != null) {
             mEventHandler = new EventHandler(looper);
@@ -101,7 +114,7 @@
         } else {
             mEventHandler = null;
         }
-        nativeInit(texName, new WeakReference<SurfaceTexture>(this));
+        nativeInit(texName, new WeakReference<SurfaceTexture>(this), allowSynchronousMode);
     }
 
     /**
@@ -209,12 +222,13 @@
         }
     }
 
-    private native void nativeInit(int texName, Object weakSelf);
+    private native void nativeInit(int texName, Object weakSelf, boolean allowSynchronousMode);
     private native void nativeFinalize();
     private native void nativeGetTransformMatrix(float[] mtx);
     private native long nativeGetTimestamp();
     private native void nativeSetDefaultBufferSize(int width, int height);
     private native void nativeUpdateTexImage();
+    private native int nativeGetQueuedCount();
 
     /*
      * We use a class initializer to allow the native code to cache some
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index a4734ff..7e03e1c 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -405,8 +405,11 @@
 
     @Override
     public void setAlpha(int alpha) {
-        mBitmapState.mPaint.setAlpha(alpha);
-        invalidateSelf();
+        int oldAlpha = mBitmapState.mPaint.getAlpha();
+        if (alpha != oldAlpha) {
+            mBitmapState.mPaint.setAlpha(alpha);
+            invalidateSelf();
+        }
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index a9414e8..b0f7fd3 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,6 +167,7 @@
         }
         if (mCurrDrawable != null) {
             mCurrDrawable.jumpToCurrentState();
+            mCurrDrawable.setAlpha(mAlpha);
         }
         if (mExitAnimationEnd != 0) {
             mExitAnimationEnd = 0;
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 9a3ca40..483fa56 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -187,8 +187,20 @@
         final int alpha = mAlpha;
         final boolean crossFade = mCrossFade;
         final ChildDrawable[] array = mLayerState.mChildren;
-        Drawable d;
 
+        if (done) {
+            // the setAlpha() calls below trigger invalidation and redraw. If we're done, just draw
+            // the appropriate drawable[s] and return
+            if (!crossFade || alpha == 0) {
+                array[0].mDrawable.draw(canvas);
+            }
+            if (alpha == 0xFF) {
+                array[1].mDrawable.draw(canvas);
+            }
+            return;
+        }
+
+        Drawable d;
         d = array[0].mDrawable;
         if (crossFade) {
             d.setAlpha(255 - alpha);
diff --git a/graphics/java/android/renderscript/Font.java b/graphics/java/android/renderscript/Font.java
index fa27590..616990a 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/graphics/java/android/renderscript/Font.java
@@ -201,12 +201,14 @@
 
     /**
      * Accepts one of the following family names as an argument
-     * and will attemp to produce the best match with a system font
+     * and will attempt to produce the best match with a system font:
+     *
      * "sans-serif" "arial" "helvetica" "tahoma" "verdana"
      * "serif" "times" "times new roman" "palatino" "georgia" "baskerville"
      * "goudy" "fantasy" "cursive" "ITC Stone Serif"
      * "monospace" "courier" "courier new" "monaco"
-     * Returns default font if no match could be found
+     *
+     * Returns default font if no match could be found.
      */
     static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize) {
         String fileName = getFontFileName(familyName, fontStyle);
diff --git a/graphics/java/android/renderscript/RSTextureView.java b/graphics/java/android/renderscript/RSTextureView.java
index f63ae8d..6046ee1 100644
--- a/graphics/java/android/renderscript/RSTextureView.java
+++ b/graphics/java/android/renderscript/RSTextureView.java
@@ -94,6 +94,12 @@
         }
     }
 
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureUpdated");
+        mSurfaceTexture = surface;
+    }
+
    /**
      * Inform the view that the activity is paused. The owner of this view must
      * call this method when the activity is paused. Calling this method will
diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h
index 317f1e7..fb0b057 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -23,10 +23,15 @@
 
 namespace android {
 
+class Surface;
+
 extern sp<ANativeWindow> android_Surface_getNativeWindow(
         JNIEnv* env, jobject clazz);
 extern bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj);
 
+/* Gets the underlying Surface from a Surface Java object. */
+extern sp<Surface> Surface_getSurface(JNIEnv* env, jobject thiz);
+
 } // namespace android
 
 #endif // _ANDROID_VIEW_SURFACE_H
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
index 74d2cc7..2d0db00 100644
--- a/include/binder/IMemory.h
+++ b/include/binder/IMemory.h
@@ -43,6 +43,7 @@
     virtual void*       getBase() const = 0;
     virtual size_t      getSize() const = 0;
     virtual uint32_t    getFlags() const = 0;
+    virtual uint32_t    getOffset() const = 0;
 
     // these are there just for backward source compatibility
     int32_t heapID() const { return getHeapID(); }
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 2f2e31b..bbbda9c 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -27,7 +27,7 @@
 
 // ---------------------------------------------------------------------------
 
-class MemoryHeapBase : public virtual BnMemoryHeap 
+class MemoryHeapBase : public virtual BnMemoryHeap
 {
 public:
     enum {
@@ -38,12 +38,12 @@
         NO_CACHING = 0x00000200
     };
 
-    /* 
+    /*
      * maps the memory referenced by fd. but DOESN'T take ownership
      * of the filedescriptor (it makes a copy with dup()
      */
     MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
-    
+
     /*
      * maps memory from the given device
      */
@@ -61,9 +61,10 @@
     virtual void*       getBase() const;
     virtual size_t      getSize() const;
     virtual uint32_t    getFlags() const;
+    virtual uint32_t      getOffset() const;
 
     const char*         getDevice() const;
-    
+
     /* this closes this heap -- use carefully */
     void dispose();
 
@@ -74,12 +75,12 @@
             mDevice = device;
         return mDevice ? NO_ERROR : ALREADY_EXISTS;
     }
-    
+
 protected:
             MemoryHeapBase();
     // init() takes ownership of fd
     status_t init(int fd, void *base, int size,
-            int flags = 0, const char* device = NULL);    
+            int flags = 0, const char* device = NULL);
 
 private:
     status_t mapfd(int fd, size_t size, uint32_t offset = 0);
@@ -90,6 +91,7 @@
     uint32_t    mFlags;
     const char* mDevice;
     bool        mNeedUnmap;
+    uint32_t    mOffset;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/binder/Permission.h b/include/binder/Permission.h
deleted file mode 100644
index 9542d50..0000000
--- a/include/binder/Permission.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BINDER_PERMISSION_H
-#define BINDER_PERMISSION_H
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <utils/SortedVector.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-/*
- * Permission caches the result of the permission check for the given
- * permission name and the provided uid/pid. It also handles a few
- * known cases efficiently (caller is in the same process or is root).
- * The package manager does something similar but lives in dalvik world
- * and is therefore extremely slow to access.
- */
-
-class Permission
-{
-public:
-            Permission(char const* name);
-            Permission(const String16& name);
-            Permission(const Permission& rhs);
-    virtual ~Permission();
-
-    bool operator < (const Permission& rhs) const;
-
-    // checks the current binder call's caller has access to this permission
-    bool checkCalling() const;
-    
-    // checks the specified pid/uid has access to this permission
-    bool check(pid_t pid, uid_t uid) const;
-    
-protected:
-    virtual bool doCheckPermission(pid_t pid, uid_t uid) const;
-
-private:
-    Permission& operator = (const Permission& rhs) const;
-    const String16 mPermissionName;
-    mutable SortedVector<uid_t> mGranted;
-    const pid_t mPid;
-    mutable Mutex mLock;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif /* BINDER_PERMISSION_H */
diff --git a/include/binder/PermissionCache.h b/include/binder/PermissionCache.h
new file mode 100644
index 0000000..1171d48
--- /dev/null
+++ b/include/binder/PermissionCache.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BINDER_PERMISSION_H
+#define BINDER_PERMISSION_H
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/String16.h>
+#include <utils/Singleton.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * PermissionCache caches permission checks for a given uid.
+ *
+ * Currently the cache is not updated when there is a permission change,
+ * for instance when an application is uninstalled.
+ *
+ * IMPORTANT: for the reason stated above, only system permissions are safe
+ * to cache. This restriction may be lifted at a later time.
+ *
+ */
+
+class PermissionCache : Singleton<PermissionCache> {
+    struct Entry {
+        String16    name;
+        uid_t       uid;
+        bool        granted;
+        inline bool operator < (const Entry& e) const {
+            return (uid == e.uid) ? (name < e.name) : (uid < e.uid);
+        }
+    };
+    mutable Mutex mLock;
+    // we pool all the permission names we see, as many permissions checks
+    // will have identical names
+    SortedVector< String16 > mPermissionNamesPool;
+    // this is our cache per say. it stores pooled names.
+    SortedVector< Entry > mCache;
+
+    // free the whole cache, but keep the permission name pool
+    void purge();
+
+    status_t check(bool* granted,
+            const String16& permission, uid_t uid) const;
+
+    void cache(const String16& permission, uid_t uid, bool granted);
+
+public:
+    PermissionCache();
+
+    static bool checkCallingPermission(const String16& permission);
+
+    static bool checkCallingPermission(const String16& permission,
+                                int32_t* outPid, int32_t* outUid);
+
+    static bool checkPermission(const String16& permission,
+            pid_t pid, uid_t uid);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* BINDER_PERMISSION_H */
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 7106bfa..f701280 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -18,9 +18,11 @@
 #define ANDROID_HARDWARE_CAMERA_H
 
 #include <utils/Timers.h>
-#include <camera/ICameraClient.h>
 #include <gui/ISurfaceTexture.h>
 #include <system/camera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
 
 namespace android {
 
@@ -70,7 +72,7 @@
     static  status_t    getCameraInfo(int cameraId,
                                       struct CameraInfo* cameraInfo);
     static  sp<Camera>  connect(int cameraId);
-                        ~Camera();
+            virtual     ~Camera();
             void        init();
 
             status_t    reconnect();
@@ -129,8 +131,11 @@
             status_t    storeMetaDataInBuffers(bool enabled);
 
             void        setListener(const sp<CameraListener>& listener);
+            void        setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
             void        setPreviewCallbackFlags(int preview_callback_flag);
 
+            sp<ICameraRecordingProxy> getRecordingProxy();
+
     // ICameraClient interface
     virtual void        notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
     virtual void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
@@ -138,6 +143,20 @@
 
     sp<ICamera>         remote();
 
+    class RecordingProxy : public BnCameraRecordingProxy
+    {
+    public:
+        RecordingProxy(const sp<Camera>& camera);
+
+        // ICameraRecordingProxy interface
+        virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener);
+        virtual void stopRecording();
+        virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+
+    private:
+        sp<Camera>         mCamera;
+    };
+
 private:
                         Camera();
                         Camera(const Camera&);
@@ -162,12 +181,12 @@
             status_t            mStatus;
 
             sp<CameraListener>  mListener;
+            sp<ICameraRecordingProxyListener>  mRecordingProxyListener;
 
             friend class DeathNotifier;
 
             static  Mutex               mLock;
             static  sp<ICameraService>  mCameraService;
-
 };
 
 }; // namespace android
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
new file mode 100644
index 0000000..2aac284
--- /dev/null
+++ b/include/camera/ICameraRecordingProxy.h
@@ -0,0 +1,101 @@
+/*
+ * 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_HARDWARE_ICAMERA_RECORDING_PROXY_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class ICameraRecordingProxyListener;
+class IMemory;
+class Parcel;
+
+/*
+ * The purpose of ICameraRecordingProxy and ICameraRecordingProxyListener is to
+ * allow applications using the camera during recording.
+ *
+ * Camera service allows only one client at a time. Since camcorder application
+ * needs to own the camera to do things like zoom, the media recorder cannot
+ * access the camera directly during recording. So ICameraRecordingProxy is a
+ * proxy of ICamera, which allows the media recorder to start/stop the recording
+ * and release recording frames. ICameraRecordingProxyListener is an interface
+ * that allows the recorder to receive video frames during recording.
+ *
+ * ICameraRecordingProxy
+ *   startRecording()
+ *   stopRecording()
+ *   releaseRecordingFrame()
+ *
+ * ICameraRecordingProxyListener
+ *   dataCallbackTimestamp()
+
+ * The camcorder app opens the camera and starts the preview. The app passes
+ * ICamera and ICameraRecordingProxy to the media recorder by
+ * MediaRecorder::setCamera(). The recorder uses ICamera to setup the camera in
+ * MediaRecorder::start(). After setup, the recorder disconnects from camera
+ * service. The recorder calls ICameraRecordingProxy::startRecording() and
+ * passes a ICameraRecordingProxyListener to the app. The app connects back to
+ * camera service and starts the recording. The app owns the camera and can do
+ * things like zoom. The media recorder receives the video frames from the
+ * listener and releases them by ICameraRecordingProxy::releaseRecordingFrame.
+ * The recorder calls ICameraRecordingProxy::stopRecording() to stop the
+ * recording.
+ *
+ * The call sequences are as follows:
+ * 1. The app: Camera.unlock().
+ * 2. The app: MediaRecorder.setCamera().
+ * 3. Start recording
+ *    (1) The app: MediaRecorder.start().
+ *    (2) The recorder: ICamera.unlock() and ICamera.disconnect().
+ *    (3) The recorder: ICameraRecordingProxy.startRecording().
+ *    (4) The app: ICamera.reconnect().
+ *    (5) The app: ICamera.startRecording().
+ * 4. During recording
+ *    (1) The recorder: receive frames from ICameraRecordingProxyListener.dataCallbackTimestamp()
+ *    (2) The recorder: release frames by ICameraRecordingProxy.releaseRecordingFrame().
+ * 5. Stop recording
+ *    (1) The app: MediaRecorder.stop()
+ *    (2) The recorder: ICameraRecordingProxy.stopRecording().
+ *    (3) The app: ICamera.stopRecording().
+ */
+
+class ICameraRecordingProxy: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(CameraRecordingProxy);
+
+    virtual status_t        startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
+    virtual void            stopRecording() = 0;
+    virtual void            releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxy: public BnInterface<ICameraRecordingProxy>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraRecordingProxyListener.h b/include/camera/ICameraRecordingProxyListener.h
new file mode 100644
index 0000000..b6c0624
--- /dev/null
+++ b/include/camera/ICameraRecordingProxyListener.h
@@ -0,0 +1,52 @@
+/*
+ * 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_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+
+#include <binder/IInterface.h>
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Parcel;
+class IMemory;
+
+class ICameraRecordingProxyListener: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(CameraRecordingProxyListener);
+
+    virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                       const sp<IMemory>& data) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxyListener: public BnInterface<ICameraRecordingProxyListener>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 9294df6..c82fb9b 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -46,17 +46,20 @@
     enum { NUM_BUFFER_SLOTS = 32 };
 
     struct FrameAvailableListener : public virtual RefBase {
-        // onFrameAvailable() is called from queueBuffer() is the FIFO is
-        // empty. You can use SurfaceTexture::getQueuedCount() to
-        // figure out if there are more frames waiting.
-        // This is called without any lock held can be called concurrently by
-        // multiple threads.
+        // onFrameAvailable() is called from queueBuffer() each time an
+        // additional frame becomes available for consumption. This means that
+        // frames that are queued while in asynchronous mode only trigger the
+        // callback if no previous frames are pending. Frames queued while in
+        // synchronous mode always trigger the callback.
+        //
+        // This is called without any lock held and can be called concurrently
+        // by multiple threads.
         virtual void onFrameAvailable() = 0;
     };
 
     // tex indicates the name OpenGL texture to which images are to be streamed.
     // This texture name cannot be changed once the SurfaceTexture is created.
-    SurfaceTexture(GLuint tex);
+    SurfaceTexture(GLuint tex, bool allowSynchronousMode = true);
 
     virtual ~SurfaceTexture();
 
@@ -101,11 +104,6 @@
     // target texture belongs is bound to the calling thread.
     status_t updateTexImage();
 
-    // getqueuedCount returns the number of queued frames waiting in the
-    // FIFO. In asynchronous mode, this always returns 0 or 1 since
-    // frames are not accumulating in the FIFO.
-    size_t getQueuedCount() const;
-
     // setBufferCountServer set the buffer count. If the client has requested
     // a buffer count using setBufferCount, the server-buffer count will
     // take effect once the client sets the count back to zero.
@@ -361,6 +359,9 @@
     // mSynchronousMode whether we're in synchronous mode or not
     bool mSynchronousMode;
 
+    // mAllowSynchronousMode whether we allow synchronous mode or not
+    const bool mAllowSynchronousMode;
+
     // mDequeueCondition condition used for dequeueBuffer in synchronous mode
     mutable Condition mDequeueCondition;
 
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 28be7c1..a73267d 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,6 +24,7 @@
 
 class Surface;
 class ICamera;
+class ICameraRecordingProxy;
 class IMediaRecorderClient;
 
 class IMediaRecorder: public IInterface
@@ -31,28 +32,29 @@
 public:
     DECLARE_META_INTERFACE(MediaRecorder);
 
-    virtual	status_t		setCamera(const sp<ICamera>& camera) = 0;
-    virtual	status_t		setPreviewSurface(const sp<Surface>& surface) = 0;
-    virtual	status_t		setVideoSource(int vs) = 0;
-    virtual	status_t		setAudioSource(int as) = 0;
-    virtual	status_t		setOutputFormat(int of) = 0;
-    virtual	status_t		setVideoEncoder(int ve) = 0;
-    virtual	status_t		setAudioEncoder(int ae) = 0;
-    virtual	status_t		setOutputFile(const char* path) = 0;
-    virtual	status_t		setOutputFile(int fd, int64_t offset, int64_t length) = 0;
-    virtual	status_t		setOutputFileAuxiliary(int fd) = 0;
-    virtual	status_t		setVideoSize(int width, int height) = 0;
-    virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
-    virtual     status_t                setParameters(const String8& params) = 0;
-    virtual     status_t                setListener(const sp<IMediaRecorderClient>& listener) = 0;
-    virtual	status_t		prepare() = 0;
-    virtual	status_t		getMaxAmplitude(int* max) = 0;
-    virtual	status_t		start() = 0;
-    virtual	status_t		stop() = 0;
-    virtual	status_t		reset() = 0;
-    virtual status_t        init() = 0;
-    virtual status_t        close() = 0;
-    virtual	status_t		release() = 0;
+    virtual status_t setCamera(const sp<ICamera>& camera,
+                               const sp<ICameraRecordingProxy>& proxy) = 0;
+    virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
+    virtual status_t setVideoSource(int vs) = 0;
+    virtual status_t setAudioSource(int as) = 0;
+    virtual status_t setOutputFormat(int of) = 0;
+    virtual status_t setVideoEncoder(int ve) = 0;
+    virtual status_t setAudioEncoder(int ae) = 0;
+    virtual status_t setOutputFile(const char* path) = 0;
+    virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
+    virtual status_t setOutputFileAuxiliary(int fd) = 0;
+    virtual status_t setVideoSize(int width, int height) = 0;
+    virtual status_t setVideoFrameRate(int frames_per_second) = 0;
+    virtual status_t setParameters(const String8& params) = 0;
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+    virtual status_t prepare() = 0;
+    virtual status_t getMaxAmplitude(int* max) = 0;
+    virtual status_t start() = 0;
+    virtual status_t stop() = 0;
+    virtual status_t reset() = 0;
+    virtual status_t init() = 0;
+    virtual status_t close() = 0;
+    virtual status_t release() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 7e22a24..1c08969 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -24,6 +24,7 @@
 
 namespace android {
 
+class ICameraRecordingProxy;
 class Surface;
 
 struct MediaRecorderBase {
@@ -38,7 +39,8 @@
     virtual status_t setVideoEncoder(video_encoder ve) = 0;
     virtual status_t setVideoSize(int width, int height) = 0;
     virtual status_t setVideoFrameRate(int frames_per_second) = 0;
-    virtual status_t setCamera(const sp<ICamera>& camera) = 0;
+    virtual status_t setCamera(const sp<ICamera>& camera,
+                               const sp<ICameraRecordingProxy>& proxy) = 0;
     virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
     virtual status_t setOutputFile(const char *path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
index 9c915ce..07567eb 100644
--- a/include/media/Metadata.h
+++ b/include/media/Metadata.h
@@ -51,47 +51,46 @@
 
     static const Type kAny = 0;
 
-    // Keep in sync with android/media/Metadata.java
-    static const Type kTitle = 1;           // String
-    static const Type kComment = 2;         // String
-    static const Type kCopyright = 3;       // String
-    static const Type kAlbum = 4;           // String
-    static const Type kArtist = 5;          // String
-    static const Type kAuthor = 6;          // String
-    static const Type kComposer = 7;        // String
-    static const Type kGenre = 8;           // String
-    static const Type kDate = 9;            // Date
-    static const Type kDuration = 10;       // Integer(millisec)
-    static const Type kCdTrackNum = 11;     // Integer 1-based
-    static const Type kCdTrackMax = 12;     // Integer
-    static const Type kRating = 13;         // String
-    static const Type kAlbumArt = 14;       // byte[]
-    static const Type kVideoFrame = 15;     // Bitmap
-    static const Type kCaption = 16;        // TimedText
+    // Playback capabilities.
+    static const Type kPauseAvailable        = 1; // Boolean
+    static const Type kSeekBackwardAvailable = 2; // Boolean
+    static const Type kSeekForwardAvailable  = 3; // Boolean
+    static const Type kSeekAvailable         = 4; // Boolean
 
-    static const Type kBitRate = 17;       // Integer, Aggregate rate of
+    // Keep in sync with android/media/Metadata.java
+    static const Type kTitle                 = 5; // String
+    static const Type kComment               = 6; // String
+    static const Type kCopyright             = 7; // String
+    static const Type kAlbum                 = 8; // String
+    static const Type kArtist                = 9; // String
+    static const Type kAuthor                = 10; // String
+    static const Type kComposer              = 11; // String
+    static const Type kGenre                 = 12; // String
+    static const Type kDate                  = 13; // Date
+    static const Type kDuration              = 14; // Integer(millisec)
+    static const Type kCdTrackNum            = 15; // Integer 1-based
+    static const Type kCdTrackMax            = 16; // Integer
+    static const Type kRating                = 17; // String
+    static const Type kAlbumArt              = 18; // byte[]
+    static const Type kVideoFrame            = 19; // Bitmap
+
+    static const Type kBitRate               = 20; // Integer, Aggregate rate of
     // all the streams in bps.
 
-    static const Type kAudioBitRate = 18; // Integer, bps
-    static const Type kVideoBitRate = 19; // Integer, bps
-    static const Type kAudioSampleRate = 20; // Integer, Hz
-    static const Type kVideoframeRate = 21;  // Integer, Hz
+    static const Type kAudioBitRate          = 21; // Integer, bps
+    static const Type kVideoBitRate          = 22; // Integer, bps
+    static const Type kAudioSampleRate       = 23; // Integer, Hz
+    static const Type kVideoframeRate        = 24; // Integer, Hz
 
     // See RFC2046 and RFC4281.
-    static const Type kMimeType = 22;      // String
-    static const Type kAudioCodec = 23;    // String
-    static const Type kVideoCodec = 24;    // String
+    static const Type kMimeType              = 25; // String
+    static const Type kAudioCodec            = 26; // String
+    static const Type kVideoCodec            = 27; // String
 
-    static const Type kVideoHeight = 25;   // Integer
-    static const Type kVideoWidth = 26;    // Integer
-    static const Type kNumTracks = 27;     // Integer
-    static const Type kDrmCrippled = 28;   // Boolean
-
-    // Playback capabilities.
-    static const Type kPauseAvailable = 29;        // Boolean
-    static const Type kSeekBackwardAvailable = 30; // Boolean
-    static const Type kSeekForwardAvailable = 31;  // Boolean
-    static const Type kSeekAvailable = 32;         // Boolean
+    static const Type kVideoHeight           = 28; // Integer
+    static const Type kVideoWidth            = 29; // Integer
+    static const Type kNumTracks             = 30; // Integer
+    static const Type kDrmCrippled           = 31; // Boolean
 
     // @param p[inout] The parcel to append the metadata records
     // to. The global metadata header should have been set already.
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 36bf34e..af12d3c 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -30,6 +30,7 @@
 class Surface;
 class IMediaRecorder;
 class ICamera;
+class ICameraRecordingProxy;
 
 typedef void (*media_completion_f)(status_t status, void *cookie);
 
@@ -202,7 +203,7 @@
 
     void        died();
     status_t    initCheck();
-    status_t    setCamera(const sp<ICamera>& camera);
+    status_t    setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     status_t    setPreviewSurface(const sp<Surface>& surface);
     status_t    setVideoSource(int vs);
     status_t    setAudioSource(int as);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index bb25bae3..80b7c1c 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -21,6 +21,7 @@
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaSource.h>
 #include <camera/ICamera.h>
+#include <camera/ICameraRecordingProxyListener.h>
 #include <camera/CameraParameters.h>
 #include <utils/List.h>
 #include <utils/RefBase.h>
@@ -68,6 +69,7 @@
      * @return NULL on error.
      */
     static CameraSource *CreateFromCamera(const sp<ICamera> &camera,
+                                          const sp<ICameraRecordingProxy> &proxy,
                                           int32_t cameraId,
                                           Size videoSize,
                                           int32_t frameRate,
@@ -111,6 +113,23 @@
     virtual void signalBufferReturned(MediaBuffer* buffer);
 
 protected:
+    class ProxyListener: public BnCameraRecordingProxyListener {
+    public:
+        ProxyListener(const sp<CameraSource>& source);
+        virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+                const sp<IMemory> &data);
+
+    private:
+        sp<CameraSource> mSource;
+    };
+
+    // isBinderAlive needs linkToDeath to work.
+    class DeathNotifier: public IBinder::DeathRecipient {
+    public:
+        DeathNotifier() {}
+        virtual void binderDied(const wp<IBinder>& who);
+    };
+
     enum CameraFlags {
         FLAGS_SET_CAMERA = 1L << 0,
         FLAGS_HOT_CAMERA = 1L << 1,
@@ -123,6 +142,8 @@
     status_t mInitCheck;
 
     sp<Camera>   mCamera;
+    sp<ICameraRecordingProxy>   mCameraRecordingProxy;
+    sp<DeathNotifier> mDeathNotifier;
     sp<Surface>  mSurface;
     sp<MetaData> mMeta;
 
@@ -132,7 +153,8 @@
     bool mStarted;
     int32_t mNumFramesEncoded;
 
-    CameraSource(const sp<ICamera>& camera, int32_t cameraId,
+    CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+                 int32_t cameraId,
                  Size videoSize, int32_t frameRate,
                  const sp<Surface>& surface,
                  bool storeMetaDataInVideoBuffers);
@@ -172,10 +194,12 @@
     void releaseOneRecordingFrame(const sp<IMemory>& frame);
 
 
-    status_t init(const sp<ICamera>& camera, int32_t cameraId,
-                Size videoSize, int32_t frameRate,
-                bool storeMetaDataInVideoBuffers);
-    status_t isCameraAvailable(const sp<ICamera>& camera, int32_t cameraId);
+    status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+                  int32_t cameraId, Size videoSize, int32_t frameRate,
+                  bool storeMetaDataInVideoBuffers);
+    status_t isCameraAvailable(const sp<ICamera>& camera,
+                               const sp<ICameraRecordingProxy>& proxy,
+                               int32_t cameraId);
     status_t isCameraColorFormatSupported(const CameraParameters& params);
     status_t configureCamera(CameraParameters* params,
                     int32_t width, int32_t height,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0e5d534..f07ebba 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -33,6 +33,7 @@
 public:
     static CameraSourceTimeLapse *CreateFromCamera(
         const sp<ICamera> &camera,
+        const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
@@ -132,6 +133,7 @@
 
     CameraSourceTimeLapse(
         const sp<ICamera> &camera,
+        const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
index 2ae8a5b..85ba920 100644
--- a/include/media/stagefright/ColorConverter.h
+++ b/include/media/stagefright/ColorConverter.h
@@ -76,6 +76,9 @@
     status_t convertYUV420SemiPlanar(
             const BitmapParams &src, const BitmapParams &dst);
 
+    status_t convertTIYUV420PackedSemiPlanar(
+            const BitmapParams &src, const BitmapParams &dst);
+
     ColorConverter(const ColorConverter &);
     ColorConverter &operator=(const ColorConverter &);
 };
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index f2c6505..e4c1c49 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -31,6 +31,10 @@
     MPEG2TSWriter(int fd);
     MPEG2TSWriter(const char *filename);
 
+    MPEG2TSWriter(
+            void *cookie,
+            ssize_t (*write)(void *cookie, const void *data, size_t size));
+
     virtual status_t addSource(const sp<MediaSource> &source);
     virtual status_t start(MetaData *param = NULL);
     virtual status_t stop();
@@ -51,6 +55,10 @@
     struct SourceInfo;
 
     FILE *mFile;
+
+    void *mWriteCookie;
+    ssize_t (*mWriteFunc)(void *cookie, const void *data, size_t size);
+
     sp<ALooper> mLooper;
     sp<AHandlerReflector<MPEG2TSWriter> > mReflector;
 
@@ -69,6 +77,8 @@
     void writeProgramMap();
     void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer);
 
+    ssize_t internalWrite(const void *data, size_t size);
+
     DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter);
 };
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index deade5e..99b72ad 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -118,6 +118,9 @@
 
     // The language code for this media
     kKeyMediaLanguage     = 'lang',  // cstring
+
+    // To store the timed text format data
+    kKeyTextFormatData    = 'text',  // raw data
 };
 
 enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 589cefd..92331a1 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -79,6 +79,13 @@
     // from MediaBufferObserver
     virtual void signalBufferReturned(MediaBuffer *buffer);
 
+    // for use by ACodec
+    static void findMatchingCodecs(
+            const char *mime,
+            bool createEncoder, const char *matchComponentName,
+            uint32_t flags,
+            Vector<String8> *matchingCodecs);
+
 protected:
     virtual ~OMXCodec();
 
@@ -311,12 +318,6 @@
     static uint32_t getComponentQuirks(
             const char *componentName, bool isEncoder);
 
-    static void findMatchingCodecs(
-            const char *mime,
-            bool createEncoder, const char *matchComponentName,
-            uint32_t flags,
-            Vector<String8> *matchingCodecs);
-
     void restorePatchedDataPointer(BufferInfo *info);
 
     status_t applyRotation();
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 12b4f93..7ed072b 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -149,6 +149,7 @@
     OMX_COLOR_Format24BitABGR6666,
     OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
     OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+    OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
diff --git a/include/pim/EventRecurrence.h b/include/pim/EventRecurrence.h
deleted file mode 100644
index 1ceda41..0000000
--- a/include/pim/EventRecurrence.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-#ifndef _PIM_EVENT_RECURRENCE_H
-#define _PIM_EVENT_RECURRENCE_H
-
-#include <utils/String16.h>
-
-namespace android {
-
-struct EventRecurrence
-{
-public:
-                EventRecurrence();
-                ~EventRecurrence();
-    
-    status_t    parse(const String16&);
-
-
-    enum freq_t {
-        SECONDLY = 1,
-        MINUTELY = 2,
-        HOURLY = 3,
-        DAILY = 4,
-        WEEKLY = 5,
-        MONTHLY = 6,
-        YEARLY = 7
-    };
-
-    enum {
-        SU = 0x00010000,
-        MO = 0x00020000,
-        TU = 0x00040000,
-        WE = 0x00080000,
-        TH = 0x00100000,
-        FR = 0x00200000,
-        SA = 0x00400000
-    };
-    
-    freq_t    freq;
-    String16  until;
-    int       count;
-    int       interval;
-    int*      bysecond;
-    int       bysecondCount;
-    int*      byminute;
-    int       byminuteCount;
-    int*      byhour;
-    int       byhourCount;
-    int*      byday;
-    int*      bydayNum;
-    int       bydayCount;   
-    int*      bymonthday;
-    int       bymonthdayCount;
-    int*      byyearday;
-    int       byyeardayCount;
-    int*      byweekno;
-    int       byweeknoCount;
-    int*      bymonth;
-    int       bymonthCount;
-    int*      bysetpos;
-    int       bysetposCount;
-    int       wkst;
-};
-
-}; // namespace android
-
-#endif // _PIM_EVENT_RECURRENCE_H
diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h
index d7fe572e..d2fed41 100644
--- a/include/private/surfaceflinger/LayerState.h
+++ b/include/private/surfaceflinger/LayerState.h
@@ -29,6 +29,7 @@
 namespace android {
 
 class Parcel;
+class ISurfaceComposerClient;
 
 struct layer_state_t {
 
@@ -68,6 +69,13 @@
             Region          transparentRegion;
 };
 
+struct ComposerState {
+    sp<ISurfaceComposerClient> client;
+    layer_state_t state;
+    status_t    write(Parcel& output) const;
+    status_t    read(const Parcel& input);
+};
+
 }; // namespace android
 
 #endif // ANDROID_SF_LAYER_STATE_H
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 03fd01b..dba98a3 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -34,6 +34,7 @@
 // ----------------------------------------------------------------------------
 
 class IMemoryHeap;
+class ComposerState;
 
 class ISurfaceComposer : public IInterface
 {
@@ -105,8 +106,7 @@
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
-    virtual void openGlobalTransaction() = 0;
-    virtual void closeGlobalTransaction() = 0;
+    virtual void setTransactionState(const Vector<ComposerState>& state) = 0;
 
     /* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */
     virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;
@@ -149,8 +149,7 @@
         CREATE_CONNECTION,
         CREATE_GRAPHIC_BUFFER_ALLOC,
         GET_CBLK,
-        OPEN_GLOBAL_TRANSACTION,
-        CLOSE_GLOBAL_TRANSACTION,
+        SET_TRANSACTION_STATE,
         SET_ORIENTATION,
         FREEZE_DISPLAY,
         UNFREEZE_DISPLAY,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 2e75a0e..6e9a654 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -37,8 +37,6 @@
 
 // ----------------------------------------------------------------------------
 
-class layer_state_t;
-
 class ISurfaceComposerClient : public IInterface
 {
 public:
@@ -69,11 +67,6 @@
      * Requires ACCESS_SURFACE_FLINGER permission
      */
     virtual status_t    destroySurface(SurfaceID sid) = 0;
-
-    /*
-     * Requires ACCESS_SURFACE_FLINGER permission
-     */
-    virtual status_t    setState(int32_t count, const layer_state_t* states) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 8845dc9..dc2a845 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -40,6 +40,7 @@
 class GraphicBuffer;
 class GraphicBufferMapper;
 class IOMX;
+class ISurfaceTexture;
 class Rect;
 class Surface;
 class SurfaceComposerClient;
@@ -154,6 +155,7 @@
     bool        isValid();
     uint32_t    getFlags() const    { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
+    sp<ISurfaceTexture> getSurfaceTexture();
 
     // the lock/unlock APIs must be used from the same thread
     status_t    lock(SurfaceInfo* info, bool blocking = true);
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 140b9f8..7fbbfb24 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -37,10 +37,12 @@
 // ---------------------------------------------------------------------------
 
 class DisplayInfo;
+class Composer;
 class IMemoryHeap;
 class ISurfaceComposer;
 class Region;
 class surface_flinger_cblk_t;
+struct layer_state_t;
 
 // ---------------------------------------------------------------------------
 
@@ -59,8 +61,11 @@
 
 // ---------------------------------------------------------------------------
 
+class Composer;
+
 class SurfaceComposerClient : public RefBase
 {
+    friend class Composer;
 public:    
                 SurfaceComposerClient();
     virtual     ~SurfaceComposerClient();
@@ -101,13 +106,7 @@
     // All composer parameters must be changed within a transaction
     // several surfaces can be updated in one transaction, all changes are
     // committed at once when the transaction is closed.
-    // CloseTransaction() usually requires an IPC with the server.
-    
-    //! Open a composer transaction
-    status_t    openTransaction();
-
-    //! commit the transaction
-    status_t    closeTransaction();
+    // closeGlobalTransaction() usually requires an IPC with the server.
 
     //! Open a composer transaction on all active SurfaceComposerClients.
     static void openGlobalTransaction();
@@ -152,19 +151,12 @@
 
 private:
     virtual void onFirstRef();
-    inline layer_state_t*   get_state_l(SurfaceID id);
-    layer_state_t*          lockLayerState(SurfaceID id);
-    inline void             unlockLayerState();
+    Composer& getComposer();
 
-    mutable     Mutex                               mLock;
-                SortedVector<layer_state_t>         mStates;
-                int32_t                             mTransactionOpen;
-                layer_state_t*                      mPrebuiltLayerState;
-
-                // these don't need to be protected because they never change
-                // after assignment
+    mutable     Mutex                       mLock;
                 status_t                    mStatus;
                 sp<ISurfaceComposerClient>  mClient;
+                Composer&                   mComposer;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/utils/LinearTransform.h b/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again).  Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+  int64_t  a_zero;
+  int64_t  b_zero;
+  int32_t  a_to_b_numer;
+  uint32_t a_to_b_denom;
+
+  // Transform from A->B
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+  // Transform from B->A
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+  // Helpers which will reduce the fraction N/D using Euclid's method.
+  template <class T> static void reduce(T* N, T* D);
+  static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif  // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index 8beec57..0e98aeb 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -32,6 +32,8 @@
 template <class TYPE>
 class SortedVector : private SortedVectorImpl
 {
+    friend class Vector<TYPE>;
+
 public:
             typedef TYPE    value_type;
     
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index f1e87e6..b908e2a 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -29,6 +29,9 @@
 
 namespace android {
 
+template <typename TYPE>
+class SortedVector;
+
 /*!
  * The main templated vector class ensuring type safety
  * while making use of VectorImpl.
@@ -47,13 +50,17 @@
     
                             Vector();
                             Vector(const Vector<TYPE>& rhs);
+    explicit                Vector(const SortedVector<TYPE>& rhs);
     virtual                 ~Vector();
 
     /*! copy operator */
             const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
             Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);    
 
-    /*
+            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
+            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);
+
+            /*
      * empty the vector
      */
 
@@ -215,6 +222,11 @@
 }
 
 template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+    : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
 Vector<TYPE>::~Vector() {
     finish_vector();
 }
@@ -227,6 +239,18 @@
 
 template<class TYPE> inline
 const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
     VectorImpl::operator = (rhs);
     return *this; 
 }
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index fd6c22c..f75208d 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -60,16 +60,17 @@
     public static final String WIFI = "WIFI_";
 
     /** Data type for public keys. */
-    public static final String PUBLIC_KEY = "KEY";
+    public static final String EXTRA_PUBLIC_KEY = "KEY";
 
     /** Data type for private keys. */
-    public static final String PRIVATE_KEY = "PKEY";
+    public static final String EXTRA_PRIVATE_KEY = "PKEY";
 
-    /** Data type for certificates. */
-    public static final String CERTIFICATE = "CERT";
-
-    /** Data type for PKCS12. */
-    public static final String PKCS12 = "PKCS12";
+    // historically used by Android
+    public static final String EXTENSION_CRT = ".crt";
+    public static final String EXTENSION_P12 = ".p12";
+    // commonly used on Windows
+    public static final String EXTENSION_CER = ".cer";
+    public static final String EXTENSION_PFX = ".pfx";
 
     /**
      * Convert objects to a PEM format, which is used for
@@ -123,18 +124,20 @@
         }
     }
 
-    private Intent createInstallIntent() {
-        Intent intent = new Intent(INSTALL_ACTION);
-        intent.setClassName("com.android.certinstaller",
-                "com.android.certinstaller.CertInstallerMain");
-        return intent;
+    public void install(Context context) {
+        try {
+            Intent intent = KeyChain.createInstallIntent();
+            context.startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Log.w(LOGTAG, e.toString());
+        }
     }
 
     public void install(Context context, KeyPair pair) {
         try {
-            Intent intent = createInstallIntent();
-            intent.putExtra(PRIVATE_KEY, pair.getPrivate().getEncoded());
-            intent.putExtra(PUBLIC_KEY, pair.getPublic().getEncoded());
+            Intent intent = KeyChain.createInstallIntent();
+            intent.putExtra(EXTRA_PRIVATE_KEY, pair.getPrivate().getEncoded());
+            intent.putExtra(EXTRA_PUBLIC_KEY, pair.getPublic().getEncoded());
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
             Log.w(LOGTAG, e.toString());
@@ -143,7 +146,7 @@
 
     public void install(Context context, String type, byte[] value) {
         try {
-            Intent intent = createInstallIntent();
+            Intent intent = KeyChain.createInstallIntent();
             intent.putExtra(type, value);
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 2763e46..23ffd59 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -30,5 +30,6 @@
     void installCaCertificate(in byte[] caCertificate);
 
     // APIs used by Settings
+    boolean deleteCaCertificate(String alias);
     boolean reset();
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 4f1596d..b567207 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -22,6 +22,7 @@
 import android.accounts.AuthenticatorException;
 import android.accounts.OperationCanceledException;
 import android.app.Activity;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -88,11 +89,117 @@
     public static final String ACCOUNT_TYPE = "com.android.keychain";
 
     /**
+     * Action to bring up the KeyChainActivity
+     */
+    private static final String ACTION_CHOOSER = "com.android.keychain.CHOOSER";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
      * @hide Also used by KeyChainActivity implementation
      */
     public static final String EXTRA_RESPONSE = "response";
 
     /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_HOST = "host";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_PORT = "port";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_ALIAS = "alias";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_SENDER = "sender";
+
+    /**
+     * Action to bring up the CertInstaller
+     */
+    private static final String ACTION_INSTALL = "android.credentials.INSTALL";
+
+    /**
+     * Optional extra to specify a {@code String} credential name on
+     * the {@code Intent} returned by {@link #createInstallIntent}.
+     *
+     * @hide TODO make public
+     */
+    // Compatible with old com.android.certinstaller.CredentialHelper.CERT_NAME_KEY
+    public static final String EXTRA_NAME = "name";
+
+    /**
+     * Optional extra to specify an X.509 certificate to install on
+     * the {@code Intent} returned by {@link #createInstallIntent}.
+     * The extra value should be a PEM or ASN.1 DER encoded {@code
+     * byte[]}. An {@link X509Certificate} can be converted to DER
+     * encoded bytes with {@link X509Certificate#getEncoded}.
+     *
+     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
+     * name for the installed certificate.
+     *
+     * @hide TODO make public
+     */
+    // Compatible with old android.security.Credentials.CERTIFICATE
+    public static final String EXTRA_CERTIFICATE = "CERT";
+
+    /**
+     * Optional extra for use with the {@code Intent} returned by
+     * {@link #createInstallIntent} to specify a PKCS#12 key store to
+     * install. The extra value should be a {@code byte[]}. The bytes
+     * may come from an external source or be generated with {@link
+     * KeyStore#store} on a "PKCS12" instance.
+     *
+     * <p>The user will be prompted for the password to load the key store.
+     *
+     * <p>The key store will be scanned for {@link
+     * java.security.KeyStore.PrivateKeyEntry} entries and both the
+     * private key and associated certificate chain will be installed.
+     *
+     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
+     * name for the installed credentials.
+     *
+     * @hide TODO make public
+     */
+    // Compatible with old android.security.Credentials.PKCS12
+    public static final String EXTRA_PKCS12 = "PKCS12";
+
+    /**
+     * Returns an {@code Intent} that can be used for credential
+     * installation. The intent may be used without any extras, in
+     * which case the user will be able to install credentials from
+     * their own source.
+     *
+     * <p>Alternatively, {@link #EXTRA_CERTIFICATE} or {@link
+     * #EXTRA_PKCS12} maybe used to specify the bytes of an X.509
+     * certificate or a PKCS#12 key store for installation. These
+     * extras may be combined with {@link EXTRA_NAME} to provide a
+     * default alias name for credentials being installed.
+     *
+     * <p>When used with {@link Activity#startActivityForResult},
+     * {@link Activity#RESULT_OK} will be returned if a credential was
+     * successfully installed, otherwise {@link
+     * Activity#RESULT_CANCELED} will be returned.
+     *
+     * @hide TODO make public with createInstallIntent, EXTRA_NAME, EXTRA_CERTIFICATE, EXTRA_PKCS12
+     */
+    public static Intent createInstallIntent() {
+        Intent intent = new Intent(ACTION_INSTALL);
+        intent.setClassName("com.android.certinstaller",
+                            "com.android.certinstaller.CertInstallerMain");
+        return intent;
+    }
+
+    /**
      * Launches an {@code Activity} for the user to select the alias
      * for a private key and certificate pair for authentication. The
      * selected alias or null will be returned via the
@@ -106,6 +213,9 @@
      * <p>{@code host} and {@code port} may be used to give the user
      * more context about the server requesting the credentials.
      *
+     * <p>{@code alias} allows the chooser to preselect an existing
+     * alias which will still be subject to user confirmation.
+     *
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#USE_CREDENTIALS}.
      *
@@ -123,14 +233,17 @@
      *     certificate, or null if unavailable.
      * @param port The port number of the server requesting the
      *     certificate, or -1 if unavailable.
+     * @param alias The alias to preselect if available, or null if
+     *     unavailable.
      */
     public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
                                              String[] keyTypes, Principal[] issuers,
-                                             String host, int port) {
+                                             String host, int port,
+                                             String alias) {
         /*
-         * TODO currently keyTypes, issuers, host, and port are
-         * unused. They are meant to follow the semantics and purpose
-         * of X509KeyManager method arguments.
+         * TODO currently keyTypes, issuers are unused. They are meant
+         * to follow the semantics and purpose of X509KeyManager
+         * method arguments.
          *
          * keyTypes would allow the list to be filtered and typically
          * will be set correctly by the server. In practice today,
@@ -142,11 +255,6 @@
          * server. Others will send none. If this is used, if there
          * are no matches after applying the constraint, it should be
          * ignored.
-         *
-         * host and port may be shown to the user if available, but it
-         * should be clear that they are not validated values, perhaps
-         * shown along with requesting application identity to clarify
-         * the source of the request.
          */
         if (activity == null) {
             throw new NullPointerException("activity == null");
@@ -154,8 +262,13 @@
         if (response == null) {
             throw new NullPointerException("response == null");
         }
-        Intent intent = new Intent("com.android.keychain.CHOOSER");
+        Intent intent = new Intent(ACTION_CHOOSER);
         intent.putExtra(EXTRA_RESPONSE, new AliasResponse(activity, response));
+        intent.putExtra(EXTRA_HOST, host);
+        intent.putExtra(EXTRA_PORT, port);
+        intent.putExtra(EXTRA_ALIAS, alias);
+        // the PendingIntent is used to get calling package name
+        intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
         activity.startActivity(intent);
     }
 
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 4582aa0..15e253c 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -75,11 +75,21 @@
         assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
     }
 
+    public void testGet() throws Exception {
+        assertNull(mKeyStore.get(TEST_KEYNAME));
+        mKeyStore.password(TEST_PASSWD);
+        assertNull(mKeyStore.get(TEST_KEYNAME));
+        assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+        assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
+    }
+
     public void testPut() throws Exception {
+        assertNull(mKeyStore.get(TEST_KEYNAME));
         assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
         assertFalse(mKeyStore.contains(TEST_KEYNAME));
         mKeyStore.password(TEST_PASSWD);
         assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+        assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
     }
 
     public void testI18n() throws Exception {
@@ -96,7 +106,9 @@
         assertTrue(mKeyStore.delete(TEST_KEYNAME));
 
         mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
+        assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
         assertTrue(mKeyStore.delete(TEST_KEYNAME));
+        assertNull(mKeyStore.get(TEST_KEYNAME));
     }
 
     public void testContains() throws Exception {
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index f9d9f25..3a12e96 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -27,7 +27,7 @@
     MemoryHeapBase.cpp \
     MemoryHeapPmem.cpp \
     Parcel.cpp \
-    Permission.cpp \
+    PermissionCache.cpp \
     ProcessState.cpp \
     Static.cpp
 
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index bc8c412..1ace8f8 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -42,11 +42,11 @@
 public:
     HeapCache();
     virtual ~HeapCache();
-    
+
     virtual void binderDied(const wp<IBinder>& who);
 
-    sp<IMemoryHeap> find_heap(const sp<IBinder>& binder); 
-    void free_heap(const sp<IBinder>& binder); 
+    sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
+    void free_heap(const sp<IBinder>& binder);
     sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
     void dump_heaps();
 
@@ -57,7 +57,7 @@
         int32_t         count;
     };
 
-    void free_heap(const wp<IBinder>& binder); 
+    void free_heap(const wp<IBinder>& binder);
 
     Mutex mHeapCacheLock;
     KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
@@ -81,11 +81,12 @@
     virtual void* getBase() const;
     virtual size_t getSize() const;
     virtual uint32_t getFlags() const;
+    virtual uint32_t getOffset() const;
 
 private:
     friend class IMemory;
     friend class HeapCache;
-    
+
     // for debugging in this module
     static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {
         return gHeapCache->find_heap(binder);
@@ -97,7 +98,7 @@
         return gHeapCache->get_heap(binder);
     }
     static inline void dump_heaps() {
-        gHeapCache->dump_heaps();       
+        gHeapCache->dump_heaps();
     }
 
     void assertMapped() const;
@@ -107,6 +108,7 @@
     mutable void*       mBase;
     mutable size_t      mSize;
     mutable uint32_t    mFlags;
+    mutable uint32_t    mOffset;
     mutable bool        mRealHeap;
     mutable Mutex       mLock;
 };
@@ -123,7 +125,7 @@
     BpMemory(const sp<IBinder>& impl);
     virtual ~BpMemory();
     virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
-    
+
 private:
     mutable sp<IMemoryHeap> mHeap;
     mutable ssize_t mOffset;
@@ -203,7 +205,7 @@
 BnMemory::BnMemory() {
 }
 
-BnMemory::~BnMemory() { 
+BnMemory::~BnMemory() {
 }
 
 status_t BnMemory::onTransact(
@@ -229,7 +231,7 @@
 
 BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl)
     : BpInterface<IMemoryHeap>(impl),
-        mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false)
+        mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false)
 {
 }
 
@@ -242,7 +244,7 @@
                 sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
 
                 if (VERBOSE) {
-                    LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d", 
+                    LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
                             binder.get(), this, mSize, mHeapId);
                     CallStack stack;
                     stack.update();
@@ -270,6 +272,7 @@
             if (mHeapId == -1) {
                 mBase   = heap->mBase;
                 mSize   = heap->mSize;
+                mOffset = heap->mOffset;
                 android_atomic_write( dup( heap->mHeapId ), &mHeapId );
             }
         } else {
@@ -286,13 +289,14 @@
         // remote call without mLock held, worse case scenario, we end up
         // calling transact() from multiple threads, but that's not a problem,
         // only mmap below must be in the critical section.
-        
+
         Parcel data, reply;
         data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
         status_t err = remote()->transact(HEAP_ID, data, &reply);
         int parcel_fd = reply.readFileDescriptor();
         ssize_t size = reply.readInt32();
         uint32_t flags = reply.readInt32();
+        uint32_t offset = reply.readInt32();
 
         LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
                 asBinder().get(), parcel_fd, size, err, strerror(-err));
@@ -309,7 +313,7 @@
         Mutex::Autolock _l(mLock);
         if (mHeapId == -1) {
             mRealHeap = true;
-            mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
+            mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
             if (mBase == MAP_FAILED) {
                 LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
                         asBinder().get(), size, fd, strerror(errno));
@@ -317,6 +321,7 @@
             } else {
                 mSize = size;
                 mFlags = flags;
+                mOffset = offset;
                 android_atomic_write(fd, &mHeapId);
             }
         }
@@ -343,14 +348,19 @@
     return mFlags;
 }
 
+uint32_t BpMemoryHeap::getOffset() const {
+    assertMapped();
+    return mOffset;
+}
+
 // ---------------------------------------------------------------------------
 
 IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
 
-BnMemoryHeap::BnMemoryHeap() { 
+BnMemoryHeap::BnMemoryHeap() {
 }
 
-BnMemoryHeap::~BnMemoryHeap() { 
+BnMemoryHeap::~BnMemoryHeap() {
 }
 
 status_t BnMemoryHeap::onTransact(
@@ -362,6 +372,7 @@
             reply->writeFileDescriptor(getHeapID());
             reply->writeInt32(getSize());
             reply->writeInt32(getFlags());
+            reply->writeInt32(getOffset());
             return NO_ERROR;
         } break;
         default:
@@ -383,17 +394,17 @@
 void HeapCache::binderDied(const wp<IBinder>& binder)
 {
     //LOGD("binderDied binder=%p", binder.unsafe_get());
-    free_heap(binder); 
+    free_heap(binder);
 }
 
-sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) 
+sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
 {
     Mutex::Autolock _l(mHeapCacheLock);
     ssize_t i = mHeapCache.indexOfKey(binder);
     if (i>=0) {
         heap_info_t& info = mHeapCache.editValueAt(i);
         LOGD_IF(VERBOSE,
-                "found binder=%p, heap=%p, size=%d, fd=%d, count=%d", 
+                "found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
                 binder.get(), info.heap.get(),
                 static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
                 static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -415,7 +426,7 @@
     free_heap( wp<IBinder>(binder) );
 }
 
-void HeapCache::free_heap(const wp<IBinder>& binder) 
+void HeapCache::free_heap(const wp<IBinder>& binder)
 {
     sp<IMemoryHeap> rel;
     {
@@ -426,7 +437,7 @@
             int32_t c = android_atomic_dec(&info.count);
             if (c == 1) {
                 LOGD_IF(VERBOSE,
-                        "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d", 
+                        "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
                         binder.unsafe_get(), info.heap.get(),
                         static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
                         static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -450,7 +461,7 @@
     return realHeap;
 }
 
-void HeapCache::dump_heaps() 
+void HeapCache::dump_heaps()
 {
     Mutex::Autolock _l(mHeapCacheLock);
     int c = mHeapCache.size();
@@ -459,7 +470,7 @@
         BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get()));
         LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)",
                 mHeapCache.keyAt(i).unsafe_get(),
-                info.heap.get(), info.count, 
+                info.heap.get(), info.count,
                 h->mHeapId, h->mBase, h->mSize);
     }
 }
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 9f501e2..bf4a73f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -40,15 +40,15 @@
 
 // ---------------------------------------------------------------------------
 
-MemoryHeapBase::MemoryHeapBase() 
+MemoryHeapBase::MemoryHeapBase()
     : mFD(-1), mSize(0), mBase(MAP_FAILED),
-      mDevice(NULL), mNeedUnmap(false) 
+      mDevice(NULL), mNeedUnmap(false), mOffset(0)
 {
 }
 
 MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
-      mDevice(0), mNeedUnmap(false)
+      mDevice(0), mNeedUnmap(false), mOffset(0)
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
@@ -65,7 +65,7 @@
 
 MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
-      mDevice(0), mNeedUnmap(false)
+      mDevice(0), mNeedUnmap(false), mOffset(0)
 {
     int open_flags = O_RDWR;
     if (flags & NO_CACHING)
@@ -84,7 +84,7 @@
 
 MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
-      mDevice(0), mNeedUnmap(false)
+      mDevice(0), mNeedUnmap(false), mOffset(0)
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
@@ -141,6 +141,7 @@
     }
     mFD = fd;
     mSize = size;
+    mOffset = offset;
     return NO_ERROR;
 }
 
@@ -183,5 +184,9 @@
     return mDevice;
 }
 
+uint32_t MemoryHeapBase::getOffset() const {
+    return mOffset;
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/binder/Permission.cpp b/libs/binder/Permission.cpp
deleted file mode 100644
index fd8fe69..0000000
--- a/libs/binder/Permission.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Permission.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-Permission::Permission(char const* name)
-    : mPermissionName(name), mPid(getpid())
-{
-}
-
-Permission::Permission(const String16& name)
-    : mPermissionName(name), mPid(getpid())
-{
-}
-
-Permission::Permission(const Permission& rhs)
-    : mPermissionName(rhs.mPermissionName),
-    mGranted(rhs.mGranted),
-    mPid(rhs.mPid)
-{
-}
-
-Permission::~Permission()
-{
-}
-
-bool Permission::operator < (const Permission& rhs) const
-{
-    return mPermissionName < rhs.mPermissionName;
-}
-
-bool Permission::checkCalling() const
-{
-    IPCThreadState* ipcState = IPCThreadState::self();
-    pid_t pid = ipcState->getCallingPid();
-    uid_t uid = ipcState->getCallingUid();
-    return doCheckPermission(pid, uid);
-}
-
-bool Permission::check(pid_t pid, uid_t uid) const
-{
-    return doCheckPermission(pid, uid);
-}
-
-bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
-{
-    if ((uid == 0) || (pid == mPid)) {
-        // root and ourselves is always okay
-        return true;
-    } else {
-        // see if we already granted this permission for this uid
-        Mutex::Autolock _l(mLock);
-        if (mGranted.indexOf(uid) >= 0)
-            return true;
-    }
-
-    bool granted = checkPermission(mPermissionName, pid, uid);
-    if (granted) {
-        Mutex::Autolock _l(mLock);
-        // no need to check again, the old item will be replaced if it is
-        // already there.
-        mGranted.add(uid);
-    }
-    return granted;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
new file mode 100644
index 0000000..7278187
--- /dev/null
+++ b/libs/binder/PermissionCache.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PermissionCache"
+
+#include <stdint.h>
+#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
+
+// ----------------------------------------------------------------------------
+
+PermissionCache::PermissionCache() {
+}
+
+status_t PermissionCache::check(bool* granted,
+        const String16& permission, uid_t uid) const {
+    Mutex::Autolock _l(mLock);
+    Entry e;
+    e.name = permission;
+    e.uid  = uid;
+    ssize_t index = mCache.indexOf(e);
+    if (index >= 0) {
+        *granted = mCache.itemAt(index).granted;
+        return NO_ERROR;
+    }
+    return NAME_NOT_FOUND;
+}
+
+void PermissionCache::cache(const String16& permission,
+        uid_t uid, bool granted) {
+    Mutex::Autolock _l(mLock);
+    Entry e;
+    ssize_t index = mPermissionNamesPool.indexOf(permission);
+    if (index > 0) {
+        e.name = mPermissionNamesPool.itemAt(index);
+    } else {
+        mPermissionNamesPool.add(permission);
+        e.name = permission;
+    }
+    // note, we don't need to store the pid, which is not actually used in
+    // permission checks
+    e.uid  = uid;
+    e.granted = granted;
+    index = mCache.indexOf(e);
+    if (index < 0) {
+        mCache.add(e);
+    }
+}
+
+void PermissionCache::purge() {
+    Mutex::Autolock _l(mLock);
+    mCache.clear();
+}
+
+bool PermissionCache::checkCallingPermission(const String16& permission) {
+    return PermissionCache::checkCallingPermission(permission, NULL, NULL);
+}
+
+bool PermissionCache::checkCallingPermission(
+        const String16& permission, int32_t* outPid, int32_t* outUid) {
+    IPCThreadState* ipcState = IPCThreadState::self();
+    pid_t pid = ipcState->getCallingPid();
+    uid_t uid = ipcState->getCallingUid();
+    if (outPid) *outPid = pid;
+    if (outUid) *outUid = uid;
+    return PermissionCache::checkPermission(permission, pid, uid);
+}
+
+bool PermissionCache::checkPermission(
+        const String16& permission, pid_t pid, uid_t uid) {
+    if ((uid == 0) || (pid == getpid())) {
+        // root and ourselves is always okay
+        return true;
+    }
+
+    PermissionCache& pc(PermissionCache::getInstance());
+    bool granted = false;
+    if (pc.check(&granted, permission, uid) != NO_ERROR) {
+        nsecs_t t = -systemTime();
+        granted = android::checkPermission(permission, pid, uid);
+        t += systemTime();
+        LOGD("checking %s for uid=%d => %s (%d us)",
+                String8(permission).string(), uid,
+                granted?"granted":"denied", (int)ns2us(t));
+        pc.cache(permission, uid, granted);
+    }
+    return granted;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index b17b3d2..dc00957 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -6,7 +6,9 @@
 	CameraParameters.cpp \
 	ICamera.cpp \
 	ICameraClient.cpp \
-	ICameraService.cpp
+	ICameraService.cpp \
+	ICameraRecordingProxy.cpp \
+	ICameraRecordingProxyListener.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 5eb48da..3c00db5 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -19,11 +19,12 @@
 #define LOG_TAG "Camera"
 #include <utils/Log.h>
 #include <utils/threads.h>
-
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
 
 #include <camera/Camera.h>
+#include <camera/ICameraRecordingProxyListener.h>
 #include <camera/ICameraService.h>
 
 #include <surfaceflinger/Surface.h>
@@ -236,6 +237,10 @@
 void Camera::stopRecording()
 {
     LOGV("stopRecording");
+    {
+        Mutex::Autolock _l(mLock);
+        mRecordingProxyListener.clear();
+    }
     sp <ICamera> c = mCamera;
     if (c == 0) return;
     c->stopRecording();
@@ -327,6 +332,12 @@
     mListener = listener;
 }
 
+void Camera::setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener)
+{
+    Mutex::Autolock _l(mLock);
+    mRecordingProxyListener = listener;
+}
+
 void Camera::setPreviewCallbackFlags(int flag)
 {
     LOGV("setPreviewCallbackFlags");
@@ -364,6 +375,19 @@
 // callback from camera service when timestamped frame is ready
 void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
 {
+    // If recording proxy listener is registered, forward the frame and return.
+    // The other listener (mListener) is ignored because the receiver needs to
+    // call releaseRecordingFrame.
+    sp<ICameraRecordingProxyListener> proxylistener;
+    {
+        Mutex::Autolock _l(mLock);
+        proxylistener = mRecordingProxyListener;
+    }
+    if (proxylistener != NULL) {
+        proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+        return;
+    }
+
     sp<CameraListener> listener;
     {
         Mutex::Autolock _l(mLock);
@@ -389,4 +413,34 @@
     LOGW("Camera server died!");
 }
 
+sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
+    LOGV("getProxy");
+    return new RecordingProxy(this);
+}
+
+status_t Camera::RecordingProxy::startRecording(const sp<ICameraRecordingProxyListener>& listener)
+{
+    LOGV("RecordingProxy::startRecording");
+    mCamera->setRecordingProxyListener(listener);
+    mCamera->reconnect();
+    return mCamera->startRecording();
+}
+
+void Camera::RecordingProxy::stopRecording()
+{
+    LOGV("RecordingProxy::stopRecording");
+    mCamera->stopRecording();
+}
+
+void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+    LOGV("RecordingProxy::releaseRecordingFrame");
+    mCamera->releaseRecordingFrame(mem);
+}
+
+Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
+{
+    mCamera = camera;
+}
+
 }; // namespace android
diff --git a/libs/camera/ICameraRecordingProxy.cpp b/libs/camera/ICameraRecordingProxy.cpp
new file mode 100644
index 0000000..64b6a5c
--- /dev/null
+++ b/libs/camera/ICameraRecordingProxy.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraRecordingProxy"
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <stdint.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+    START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
+    STOP_RECORDING,
+    RELEASE_RECORDING_FRAME,
+};
+
+
+class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
+{
+public:
+    BpCameraRecordingProxy(const sp<IBinder>& impl)
+        : BpInterface<ICameraRecordingProxy>(impl)
+    {
+    }
+
+    status_t startRecording(const sp<ICameraRecordingProxyListener>& listener)
+    {
+        LOGV("startRecording");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        data.writeStrongBinder(listener->asBinder());
+        remote()->transact(START_RECORDING, data, &reply);
+        return reply.readInt32();
+    }
+
+    void stopRecording()
+    {
+        LOGV("stopRecording");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        remote()->transact(STOP_RECORDING, data, &reply);
+    }
+
+    void releaseRecordingFrame(const sp<IMemory>& mem)
+    {
+        LOGV("releaseRecordingFrame");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        data.writeStrongBinder(mem->asBinder());
+        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxy::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case START_RECORDING: {
+            LOGV("START_RECORDING");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+            sp<ICameraRecordingProxyListener> listener =
+                interface_cast<ICameraRecordingProxyListener>(data.readStrongBinder());
+            reply->writeInt32(startRecording(listener));
+            return NO_ERROR;
+        } break;
+        case STOP_RECORDING: {
+            LOGV("STOP_RECORDING");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+            stopRecording();
+            return NO_ERROR;
+        } break;
+        case RELEASE_RECORDING_FRAME: {
+            LOGV("RELEASE_RECORDING_FRAME");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+            sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+            releaseRecordingFrame(mem);
+            return NO_ERROR;
+        } break;
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/camera/ICameraRecordingProxyListener.cpp b/libs/camera/ICameraRecordingProxyListener.cpp
new file mode 100644
index 0000000..f8cece5
--- /dev/null
+++ b/libs/camera/ICameraRecordingProxyListener.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraRecordingProxyListener"
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+    DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
+{
+public:
+    BpCameraRecordingProxyListener(const sp<IBinder>& impl)
+        : BpInterface<ICameraRecordingProxyListener>(impl)
+    {
+    }
+
+    void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+    {
+        LOGV("dataCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+        data.writeInt64(timestamp);
+        data.writeInt32(msgType);
+        data.writeStrongBinder(imageData->asBinder());
+        remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxyListener::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DATA_CALLBACK_TIMESTAMP: {
+            LOGV("DATA_CALLBACK_TIMESTAMP");
+            CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+            nsecs_t timestamp = data.readInt64();
+            int32_t msgType = data.readInt32();
+            sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+            dataCallbackTimestamp(timestamp, msgType, imageData);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 40450a3..c1156d5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,6 +25,8 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
+#include <private/surfaceflinger/LayerState.h>
+
 #include <surfaceflinger/ISurfaceComposer.h>
 
 #include <ui/DisplayInfo.h>
@@ -74,18 +76,17 @@
         return interface_cast<IMemoryHeap>(reply.readStrongBinder());
     }
 
-    virtual void openGlobalTransaction()
+    virtual void setTransactionState(const Vector<ComposerState>& state)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply);
-    }
-
-    virtual void closeGlobalTransaction()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply);
+        Vector<ComposerState>::const_iterator b(state.begin());
+        Vector<ComposerState>::const_iterator e(state.end());
+        data.writeInt32(state.size());
+        for ( ; b != e ; ++b ) {
+            b->write(data);
+        }
+        remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
     virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags)
@@ -218,13 +219,17 @@
             sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
             reply->writeStrongBinder(b);
         } break;
-        case OPEN_GLOBAL_TRANSACTION: {
+        case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            openGlobalTransaction();
-        } break;
-        case CLOSE_GLOBAL_TRANSACTION: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            closeGlobalTransaction();
+            size_t count = data.readInt32();
+            ComposerState s;
+            Vector<ComposerState> state;
+            state.setCapacity(count);
+            for (size_t i=0 ; i<count ; i++) {
+                s.read(data);
+                state.add(s);
+            }
+            setTransactionState(state);
         } break;
         case SET_ORIENTATION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 8d83392..bc97cac 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -51,8 +51,7 @@
 
 enum {
     CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
-    DESTROY_SURFACE,
-    SET_STATE
+    DESTROY_SURFACE
 };
 
 class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
@@ -92,17 +91,6 @@
         remote()->transact(DESTROY_SURFACE, data, &reply);
         return reply.readInt32();
     }
-
-    virtual status_t setState(int32_t count, const layer_state_t* states)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeInt32(count);
-        for (int i=0 ; i<count ; i++)
-            states[i].write(data);
-        remote()->transact(SET_STATE, data, &reply);
-        return reply.readInt32();
-    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
@@ -133,17 +121,6 @@
             reply->writeInt32( destroySurface( data.readInt32() ) );
             return NO_ERROR;
         } break;
-        case SET_STATE: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            int32_t count = data.readInt32();
-            layer_state_t* states = new layer_state_t[count];
-            for (int i=0 ; i<count ; i++)
-                states[i].read(data);
-            status_t err = setState(count, states);
-            delete [] states;
-            reply->writeInt32(err);
-            return NO_ERROR;
-        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 01c4c7e..87901e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -17,6 +17,7 @@
 #include <utils/Errors.h>
 #include <binder/Parcel.h>
 #include <private/surfaceflinger/LayerState.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
 
 namespace android {
 
@@ -58,4 +59,14 @@
     return NO_ERROR;
 }
 
+status_t ComposerState::write(Parcel& output) const {
+    output.writeStrongBinder(client->asBinder());
+    return state.write(output);
+}
+
+status_t ComposerState::read(const Parcel& input) {
+    client = interface_cast<ISurfaceComposerClient>(input.readStrongBinder());
+    return state.read(input);
+}
+
 }; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 4d1d923..9185e1e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -421,6 +421,10 @@
     return NO_ERROR;
 }
 
+sp<ISurfaceTexture> Surface::getSurfaceTexture() {
+    return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL;
+}
+
 sp<IBinder> Surface::asBinder() const {
     return mSurface!=0 ? mSurface->asBinder() : 0;
 }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1678711..8cead80 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -74,75 +74,52 @@
 
 // ---------------------------------------------------------------------------
 
+// NOTE: this is NOT a member function (it's a friend defined with its
+// declaration).
+static inline
+int compare_type( const ComposerState& lhs, const ComposerState& rhs) {
+    if (lhs.client < rhs.client)  return -1;
+    if (lhs.client > rhs.client)  return 1;
+    if (lhs.state.surface < rhs.state.surface)  return -1;
+    if (lhs.state.surface > rhs.state.surface)  return 1;
+    return 0;
+}
+
 class Composer : public Singleton<Composer>
 {
-    Mutex mLock;
-    SortedVector< wp<SurfaceComposerClient> > mActiveConnections;
-    SortedVector<sp<SurfaceComposerClient> > mOpenTransactions;
-
-    Composer() : Singleton<Composer>() {
-    }
-
-    void addClientImpl(const sp<SurfaceComposerClient>& client) {
-        Mutex::Autolock _l(mLock);
-        mActiveConnections.add(client);
-    }
-
-    void removeClientImpl(const sp<SurfaceComposerClient>& client) {
-        Mutex::Autolock _l(mLock);
-        mActiveConnections.remove(client);
-    }
-
-    void openGlobalTransactionImpl()
-    {
-        Mutex::Autolock _l(mLock);
-        if (mOpenTransactions.size()) {
-            LOGE("openGlobalTransaction() called more than once. skipping.");
-            return;
-        }
-        const size_t N = mActiveConnections.size();
-        for (size_t i=0; i<N; i++) {
-            sp<SurfaceComposerClient> client(mActiveConnections[i].promote());
-            if (client != 0 && mOpenTransactions.indexOf(client) < 0) {
-                if (client->openTransaction() == NO_ERROR) {
-                    mOpenTransactions.add(client);
-                } else {
-                    LOGE("openTransaction on client %p failed", client.get());
-                    // let it go, it'll fail later when the user
-                    // tries to do something with the transaction
-                }
-            }
-        }
-    }
-
-    void closeGlobalTransactionImpl()
-    {
-        mLock.lock();
-            SortedVector< sp<SurfaceComposerClient> > clients(mOpenTransactions);
-            mOpenTransactions.clear();
-        mLock.unlock();
-
-        sp<ISurfaceComposer> sm(getComposerService());
-        sm->openGlobalTransaction();
-            const size_t N = clients.size();
-            for (size_t i=0; i<N; i++) {
-                clients[i]->closeTransaction();
-            }
-        sm->closeGlobalTransaction();
-    }
-
     friend class Singleton<Composer>;
 
+    mutable Mutex               mLock;
+    SortedVector<ComposerState> mStates;
+
+    Composer() : Singleton<Composer>() { }
+
+    void closeGlobalTransactionImpl();
+
+    layer_state_t* getLayerStateLocked(
+            const sp<SurfaceComposerClient>& client, SurfaceID id);
+
 public:
-    static void addClient(const sp<SurfaceComposerClient>& client) {
-        Composer::getInstance().addClientImpl(client);
-    }
-    static void removeClient(const sp<SurfaceComposerClient>& client) {
-        Composer::getInstance().removeClientImpl(client);
-    }
-    static void openGlobalTransaction() {
-        Composer::getInstance().openGlobalTransactionImpl();
-    }
+
+    status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            int32_t x, int32_t y);
+    status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            uint32_t w, uint32_t h);
+    status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            int32_t z);
+    status_t setFlags(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            uint32_t flags, uint32_t mask);
+    status_t setTransparentRegionHint(
+            const sp<SurfaceComposerClient>& client, SurfaceID id,
+            const Region& transparentRegion);
+    status_t setAlpha(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            float alpha);
+    status_t setMatrix(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            float dsdx, float dtdx, float dsdy, float dtdy);
+    status_t setFreezeTint(
+            const sp<SurfaceComposerClient>& client, SurfaceID id,
+            uint32_t tint);
+
     static void closeGlobalTransaction() {
         Composer::getInstance().closeGlobalTransactionImpl();
     }
@@ -152,69 +129,306 @@
 
 // ---------------------------------------------------------------------------
 
-static inline int compare_type( const layer_state_t& lhs,
-                                const layer_state_t& rhs) {
-    if (lhs.surface < rhs.surface)  return -1;
-    if (lhs.surface > rhs.surface)  return 1;
-    return 0;
+void Composer::closeGlobalTransactionImpl() {
+    sp<ISurfaceComposer> sm(getComposerService());
+
+    Vector<ComposerState> transaction;
+
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        transaction = mStates;
+        mStates.clear();
+    }
+
+   sm->setTransactionState(transaction);
 }
 
+layer_state_t* Composer::getLayerStateLocked(
+        const sp<SurfaceComposerClient>& client, SurfaceID id) {
+
+    ComposerState s;
+    s.client = client->mClient;
+    s.state.surface = id;
+
+    ssize_t index = mStates.indexOf(s);
+    if (index < 0) {
+        // we don't have it, add an initialized layer_state to our list
+        index = mStates.add(s);
+    }
+
+    ComposerState* const out = mStates.editArray();
+    return &(out[index].state);
+}
+
+status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, int32_t x, int32_t y) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::ePositionChanged;
+    s->x = x;
+    s->y = y;
+    return NO_ERROR;
+}
+
+status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, uint32_t w, uint32_t h) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eSizeChanged;
+    s->w = w;
+    s->h = h;
+    return NO_ERROR;
+}
+
+status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, int32_t z) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eLayerChanged;
+    s->z = z;
+    return NO_ERROR;
+}
+
+status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, uint32_t flags,
+        uint32_t mask) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eVisibilityChanged;
+    s->flags &= ~mask;
+    s->flags |= (flags & mask);
+    s->mask |= mask;
+    return NO_ERROR;
+}
+
+status_t Composer::setTransparentRegionHint(
+        const sp<SurfaceComposerClient>& client, SurfaceID id,
+        const Region& transparentRegion) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eTransparentRegionChanged;
+    s->transparentRegion = transparentRegion;
+    return NO_ERROR;
+}
+
+status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, float alpha) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eAlphaChanged;
+    s->alpha = alpha;
+    return NO_ERROR;
+}
+
+status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, float dsdx, float dtdx,
+        float dsdy, float dtdy) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eMatrixChanged;
+    layer_state_t::matrix22_t matrix;
+    matrix.dsdx = dsdx;
+    matrix.dtdx = dtdx;
+    matrix.dsdy = dsdy;
+    matrix.dtdy = dtdy;
+    s->matrix = matrix;
+    return NO_ERROR;
+}
+
+status_t Composer::setFreezeTint(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, uint32_t tint) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eFreezeTintChanged;
+    s->tint = tint;
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
 SurfaceComposerClient::SurfaceComposerClient()
-    : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT)
+    : mStatus(NO_INIT), mComposer(Composer::getInstance())
 {
 }
 
-void SurfaceComposerClient::onFirstRef()
-{
+void SurfaceComposerClient::onFirstRef() {
     sp<ISurfaceComposer> sm(getComposerService());
     if (sm != 0) {
         sp<ISurfaceComposerClient> conn = sm->createConnection();
         if (conn != 0) {
             mClient = conn;
-            Composer::addClient(this);
-            mPrebuiltLayerState = new layer_state_t;
             mStatus = NO_ERROR;
         }
     }
 }
 
-SurfaceComposerClient::~SurfaceComposerClient()
-{
-    delete mPrebuiltLayerState;
+SurfaceComposerClient::~SurfaceComposerClient() {
     dispose();
 }
 
-status_t SurfaceComposerClient::initCheck() const
-{
+status_t SurfaceComposerClient::initCheck() const {
     return mStatus;
 }
 
-sp<IBinder> SurfaceComposerClient::connection() const
-{
+sp<IBinder> SurfaceComposerClient::connection() const {
     return (mClient != 0) ? mClient->asBinder() : 0;
 }
 
 status_t SurfaceComposerClient::linkToComposerDeath(
         const sp<IBinder::DeathRecipient>& recipient,
-        void* cookie, uint32_t flags)
-{
+        void* cookie, uint32_t flags) {
     sp<ISurfaceComposer> sm(getComposerService());
     return sm->asBinder()->linkToDeath(recipient, cookie, flags);
 }
 
-void SurfaceComposerClient::dispose()
-{
+void SurfaceComposerClient::dispose() {
     // this can be called more than once.
     sp<ISurfaceComposerClient> client;
     Mutex::Autolock _lm(mLock);
     if (mClient != 0) {
-        Composer::removeClient(this);
         client = mClient; // hold ref while lock is held
         mClient.clear();
     }
     mStatus = NO_INIT;
 }
 
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    String8 name;
+    const size_t SIZE = 128;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "<pid_%d>", getpid());
+    name.append(buffer);
+
+    return SurfaceComposerClient::createSurface(name, display,
+            w, h, format, flags);
+}
+
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+        const String8& name,
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    sp<SurfaceControl> result;
+    if (mStatus == NO_ERROR) {
+        ISurfaceComposerClient::surface_data_t data;
+        sp<ISurface> surface = mClient->createSurface(&data, name,
+                display, w, h, format, flags);
+        if (surface != 0) {
+            result = new SurfaceControl(this, surface, data, w, h, format, flags);
+        }
+    }
+    return result;
+}
+
+status_t SurfaceComposerClient::destroySurface(SurfaceID sid) {
+    if (mStatus != NO_ERROR)
+        return mStatus;
+    status_t err = mClient->destroySurface(sid);
+    return err;
+}
+
+inline Composer& SurfaceComposerClient::getComposer() {
+    return mComposer;
+}
+
+// ----------------------------------------------------------------------------
+
+void SurfaceComposerClient::openGlobalTransaction() {
+    // Currently a no-op
+}
+
+void SurfaceComposerClient::closeGlobalTransaction() {
+    Composer::closeGlobalTransaction();
+}
+
+// ----------------------------------------------------------------------------
+
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
+    return getComposer().setFreezeTint(this, id, tint);
+}
+
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) {
+    return getComposer().setPosition(this, id, x, y);
+}
+
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) {
+    return getComposer().setSize(this, id, w, h);
+}
+
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) {
+    return getComposer().setLayer(this, id, z);
+}
+
+status_t SurfaceComposerClient::hide(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            ISurfaceComposer::eLayerHidden,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t) {
+    return getComposer().setFlags(this, id,
+            0,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::freeze(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            ISurfaceComposer::eLayerFrozen,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::unfreeze(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            0,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags,
+        uint32_t mask) {
+    return getComposer().setFlags(this, id, flags, mask);
+}
+
+status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id,
+        const Region& transparentRegion) {
+    return getComposer().setTransparentRegionHint(this, id, transparentRegion);
+}
+
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) {
+    return getComposer().setAlpha(this, id, alpha);
+}
+
+status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx,
+        float dsdy, float dtdy) {
+    return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
+}
+
+// ----------------------------------------------------------------------------
+
 status_t SurfaceComposerClient::getDisplayInfo(
         DisplayID dpy, DisplayInfo* info)
 {
@@ -273,70 +487,7 @@
     return n;
 }
 
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        DisplayID display,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags)
-{
-    String8 name;
-    const size_t SIZE = 128;
-    char buffer[SIZE];
-    snprintf(buffer, SIZE, "<pid_%d>", getpid());
-    name.append(buffer);
-
-    return SurfaceComposerClient::createSurface(name, display,
-            w, h, format, flags);
-}
-
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        const String8& name,
-        DisplayID display,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags)
-{
-    sp<SurfaceControl> result;
-    if (mStatus == NO_ERROR) {
-        ISurfaceComposerClient::surface_data_t data;
-        sp<ISurface> surface = mClient->createSurface(&data, name,
-                display, w, h, format, flags);
-        if (surface != 0) {
-            result = new SurfaceControl(this, surface, data, w, h, format, flags);
-        }
-    }
-    return result;
-}
-
-status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
-{
-    if (mStatus != NO_ERROR)
-        return mStatus;
-
-    // it's okay to destroy a surface while a transaction is open,
-    // (transactions really are a client-side concept)
-    // however, this indicates probably a misuse of the API or a bug
-    // in the client code.
-    LOGW_IF(mTransactionOpen,
-         "Destroying surface while a transaction is open. "
-         "Client %p: destroying surface %d, mTransactionOpen=%d",
-         this, sid, mTransactionOpen);
-
-    status_t err = mClient->destroySurface(sid);
-    return err;
-}
-
-void SurfaceComposerClient::openGlobalTransaction()
-{
-    Composer::openGlobalTransaction();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction()
-{
-    Composer::closeGlobalTransaction();
-}
+// ----------------------------------------------------------------------------
 
 status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
 {
@@ -350,199 +501,13 @@
     return sm->unfreezeDisplay(dpy, flags);
 }
 
-int SurfaceComposerClient::setOrientation(DisplayID dpy, 
+int SurfaceComposerClient::setOrientation(DisplayID dpy,
         int orientation, uint32_t flags)
 {
     sp<ISurfaceComposer> sm(getComposerService());
     return sm->setOrientation(dpy, orientation, flags);
 }
 
-status_t SurfaceComposerClient::openTransaction()
-{
-    if (mStatus != NO_ERROR)
-        return mStatus;
-    Mutex::Autolock _l(mLock);
-    mTransactionOpen++;
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::closeTransaction()
-{
-    if (mStatus != NO_ERROR)
-        return mStatus;
-
-    Mutex::Autolock _l(mLock);
-    if (mTransactionOpen <= 0) {
-        LOGE(   "closeTransaction (client %p, mTransactionOpen=%d) "
-                "called more times than openTransaction()",
-                this, mTransactionOpen);
-        return INVALID_OPERATION;
-    }
-
-    if (mTransactionOpen >= 2) {
-        mTransactionOpen--;
-        return NO_ERROR;
-    }
-
-    mTransactionOpen = 0;
-    const ssize_t count = mStates.size();
-    if (count) {
-        mClient->setState(count, mStates.array());
-        mStates.clear();
-    }
-    return NO_ERROR;
-}
-
-layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index)
-{
-    // API usage error, do nothing.
-    if (mTransactionOpen<=0) {
-        LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
-                this, int(index), mTransactionOpen);
-        return 0;
-    }
-
-    // use mPrebuiltLayerState just to find out if we already have it
-    layer_state_t& dummy(*mPrebuiltLayerState);
-    dummy.surface = index;
-    ssize_t i = mStates.indexOf(dummy);
-    if (i < 0) {
-        // we don't have it, add an initialized layer_state to our list
-        i = mStates.add(dummy);
-    }
-    return mStates.editArray() + i;
-}
-
-layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id)
-{
-    layer_state_t* s;
-    mLock.lock();
-    s = get_state_l(id);
-    if (!s) mLock.unlock();
-    return s;
-}
-
-void SurfaceComposerClient::unlockLayerState()
-{
-    mLock.unlock();
-}
-
-status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::ePositionChanged;
-    s->x = x;
-    s->y = y;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eSizeChanged;
-    s->w = w;
-    s->h = h;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eLayerChanged;
-    s->z = z;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::hide(SurfaceID id)
-{
-    return setFlags(id, ISurfaceComposer::eLayerHidden,
-            ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
-{
-    return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::freeze(SurfaceID id)
-{
-    return setFlags(id, ISurfaceComposer::eLayerFrozen,
-            ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::unfreeze(SurfaceID id)
-{
-    return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::setFlags(SurfaceID id,
-        uint32_t flags, uint32_t mask)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eVisibilityChanged;
-    s->flags &= ~mask;
-    s->flags |= (flags & mask);
-    s->mask |= mask;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(
-        SurfaceID id, const Region& transparentRegion)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eTransparentRegionChanged;
-    s->transparentRegion = transparentRegion;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eAlphaChanged;
-    s->alpha = alpha;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setMatrix(
-        SurfaceID id,
-        float dsdx, float dtdx,
-        float dsdy, float dtdy )
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eMatrixChanged;
-    layer_state_t::matrix22_t matrix;
-    matrix.dsdx = dsdx;
-    matrix.dtdx = dtdx;
-    matrix.dsdy = dsdy;
-    matrix.dtdy = dtdy;
-    s->matrix = matrix;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eFreezeTintChanged;
-    s->tint = tint;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 
 ScreenshotClient::ScreenshotClient()
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 3cecdb4..0925001 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -78,7 +78,7 @@
 
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
-SurfaceTexture::SurfaceTexture(GLuint tex) :
+SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
     mDefaultWidth(1),
     mDefaultHeight(1),
     mPixelFormat(PIXEL_FORMAT_RGBA_8888),
@@ -91,7 +91,8 @@
     mCurrentTimestamp(0),
     mNextTransform(0),
     mTexName(tex),
-    mSynchronousMode(false) {
+    mSynchronousMode(false),
+    mAllowSynchronousMode(allowSynchronousMode) {
     LOGV("SurfaceTexture::SurfaceTexture");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -371,6 +372,9 @@
     Mutex::Autolock lock(mMutex);
 
     status_t err = OK;
+    if (!mAllowSynchronousMode && enabled)
+        return err;
+
     if (!enabled) {
         // going to asynchronous mode, drain the queue
         while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
@@ -413,17 +417,22 @@
             return -EINVAL;
         }
 
-        if (mQueue.empty()) {
-            listener = mFrameAvailableListener;
-        }
-
         if (mSynchronousMode) {
-            // in synchronous mode we queue all buffers in a FIFO
+            // In synchronous mode we queue all buffers in a FIFO.
             mQueue.push_back(buf);
+
+            // Synchronous mode always signals that an additional frame should
+            // be consumed.
+            listener = mFrameAvailableListener;
         } else {
-            // in asynchronous mode we only keep the most recent buffer
+            // In asynchronous mode we only keep the most recent buffer.
             if (mQueue.empty()) {
                 mQueue.push_back(buf);
+
+                // Asynchronous mode only signals that a frame should be
+                // consumed if no previous frame was pending. If a frame were
+                // pending then the consumer would have already been notified.
+                listener = mFrameAvailableListener;
             } else {
                 Fifo::iterator front(mQueue.begin());
                 // buffer currently queued is freed
@@ -479,24 +488,14 @@
 
 status_t SurfaceTexture::updateTexImage() {
     LOGV("SurfaceTexture::updateTexImage");
-
     Mutex::Autolock lock(mMutex);
 
-    int buf = mCurrentTexture;
+    // In asynchronous mode the list is guaranteed to be one buffer
+    // deep, while in synchronous mode we use the oldest buffer.
     if (!mQueue.empty()) {
-        // in asynchronous mode the list is guaranteed to be one buffer deep,
-        // while in synchronous mode we use the oldest buffer
         Fifo::iterator front(mQueue.begin());
-        buf = *front;
-        mQueue.erase(front);
-        if (mQueue.isEmpty()) {
-            mDequeueCondition.signal();
-        }
-    }
+        int buf = *front;
 
-    // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
-    // so this check will fail until a buffer gets queued.
-    if (mCurrentTexture != buf) {
         // Update the GL texture object.
         EGLImageKHR image = mSlots[buf].mEglImage;
         if (image == EGL_NO_IMAGE_KHR) {
@@ -534,7 +533,7 @@
         }
 
         if (mCurrentTexture != INVALID_BUFFER_SLOT) {
-            // the current buffer becomes FREE if it was still in the queued
+            // The current buffer becomes FREE if it was still in the queued
             // state. If it has already been given to the client
             // (synchronous mode), then it stays in DEQUEUED state.
             if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
@@ -549,17 +548,17 @@
         mCurrentTransform = mSlots[buf].mTransform;
         mCurrentTimestamp = mSlots[buf].mTimestamp;
         computeCurrentTransformMatrix();
+
+        // Now that we've passed the point at which failures can happen,
+        // it's safe to remove the buffer from the front of the queue.
+        mQueue.erase(front);
         mDequeueCondition.signal();
     } else {
         // We always bind the texture even if we don't update its contents.
         glBindTexture(mCurrentTextureTarget, mTexName);
     }
-    return OK;
-}
 
-size_t SurfaceTexture::getQueuedCount() const {
-    Mutex::Autolock lock(mMutex);
-    return mQueue.size();
+    return OK;
 }
 
 bool SurfaceTexture::isExternalFormat(uint32_t format)
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index f219639..c06400e 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -84,10 +84,10 @@
             ASSERT_TRUE(mSurfaceControl != NULL);
             ASSERT_TRUE(mSurfaceControl->isValid());
 
-            ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
+            SurfaceComposerClient::openGlobalTransaction();
             ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
             ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-            ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+            SurfaceComposerClient::closeGlobalTransaction();
 
             sp<ANativeWindow> window = mSurfaceControl->getSurface();
             mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
@@ -419,6 +419,31 @@
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
     }
 
+    class FrameWaiter : public SurfaceTexture::FrameAvailableListener {
+    public:
+        FrameWaiter():
+                mPendingFrames(0) {
+        }
+
+        void waitForFrame() {
+            Mutex::Autolock lock(mMutex);
+            while (mPendingFrames == 0) {
+                mCondition.wait(mMutex);
+            }
+            mPendingFrames--;
+        }
+
+        virtual void onFrameAvailable() {
+            Mutex::Autolock lock(mMutex);
+            mPendingFrames++;
+            mCondition.signal();
+        }
+
+        int mPendingFrames;
+        Mutex mMutex;
+        Condition mCondition;
+    };
+
     sp<SurfaceTexture> mST;
     sp<SurfaceTextureClient> mSTC;
     sp<ANativeWindow> mANW;
@@ -648,6 +673,157 @@
     }
 }
 
+// This test is intended to catch synchronization bugs between the CPU-written
+// and GPU-read buffers.
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
+    enum { texWidth = 16 };
+    enum { texHeight = 16 };
+    enum { numFrames = 1024 };
+
+    ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
+    ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    struct TestPixel {
+        int x;
+        int y;
+    };
+    const TestPixel testPixels[] = {
+        {  4, 11 },
+        { 12, 14 },
+        {  7,  2 },
+    };
+    enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])};
+
+    class ProducerThread : public Thread {
+    public:
+        ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels):
+                mANW(anw),
+                mTestPixels(testPixels) {
+        }
+
+        virtual ~ProducerThread() {
+        }
+
+        virtual bool threadLoop() {
+            for (int i = 0; i < numFrames; i++) {
+                ANativeWindowBuffer* anb;
+                if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+                    return false;
+                }
+                if (anb == NULL) {
+                    return false;
+                }
+
+                sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+                if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())
+                        != NO_ERROR) {
+                    return false;
+                }
+
+                const int yuvTexOffsetY = 0;
+                int stride = buf->getStride();
+                int yuvTexStrideY = stride;
+                int yuvTexOffsetV = yuvTexStrideY * texHeight;
+                int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+                int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2;
+                int yuvTexStrideU = yuvTexStrideV;
+
+                uint8_t* img = NULL;
+                buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+                // Gray out all the test pixels first, so we're more likely to
+                // see a failure if GL is still texturing from the buffer we
+                // just dequeued.
+                for (int j = 0; j < numTestPixels; j++) {
+                    int x = mTestPixels[j].x;
+                    int y = mTestPixels[j].y;
+                    uint8_t value = 128;
+                    img[y*stride + x] = value;
+                }
+
+                // Fill the buffer with gray.
+                for (int y = 0; y < texHeight; y++) {
+                    for (int x = 0; x < texWidth; x++) {
+                        img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128;
+                        img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128;
+                        img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128;
+                    }
+                }
+
+                // Set the test pixels to either white or black.
+                for (int j = 0; j < numTestPixels; j++) {
+                    int x = mTestPixels[j].x;
+                    int y = mTestPixels[j].y;
+                    uint8_t value = 0;
+                    if (j == (i % numTestPixels)) {
+                        value = 255;
+                    }
+                    img[y*stride + x] = value;
+                }
+
+                buf->unlock();
+                if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())
+                        != NO_ERROR) {
+                    return false;
+                }
+            }
+            return false;
+        }
+
+        sp<ANativeWindow> mANW;
+        const TestPixel* mTestPixels;
+    };
+
+    sp<FrameWaiter> fw(new FrameWaiter);
+    mST->setFrameAvailableListener(fw);
+
+    sp<Thread> pt(new ProducerThread(mANW, testPixels));
+    pt->run();
+
+    glViewport(0, 0, texWidth, texHeight);
+
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // We wait for the first two frames up front so that the producer will be
+    // likely to dequeue the buffer that's currently being textured from.
+    fw->waitForFrame();
+    fw->waitForFrame();
+
+    for (int i = 0; i < numFrames; i++) {
+        SCOPED_TRACE(String8::format("frame %d", i).string());
+
+        // We must wait for each frame to come in because if we ever do an
+        // updateTexImage call that doesn't consume a newly available buffer
+        // then the producer and consumer will get out of sync, which will cause
+        // a deadlock.
+        if (i > 1) {
+            fw->waitForFrame();
+        }
+        mST->updateTexImage();
+        drawTexture();
+
+        for (int j = 0; j < numTestPixels; j++) {
+            int x = testPixels[j].x;
+            int y = testPixels[j].y;
+            uint8_t value = 0;
+            if (j == (i % numTestPixels)) {
+                // We must y-invert the texture coords
+                EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255));
+            } else {
+                // We must y-invert the texture coords
+                EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255));
+            }
+        }
+    }
+
+    pt->requestExitAndWait();
+}
+
 // XXX: This test is disabled because there are currently no drivers that can
 // handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
 TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 35c8640..450cdf1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -36,10 +36,10 @@
         ASSERT_TRUE(mSurfaceControl != NULL);
         ASSERT_TRUE(mSurfaceControl->isValid());
 
-        ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
+        SurfaceComposerClient::openGlobalTransaction();
         ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000));
         ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-        ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+        SurfaceComposerClient::closeGlobalTransaction();
 
         mSurface = mSurfaceControl->getSurface();
         ASSERT_TRUE(mSurface != NULL);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index b0d8cf9..563d7e4 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -57,7 +57,7 @@
     LOGD("Enabling debug mode %d", mDebugLevel);
 
 #if RENDER_LAYERS_AS_REGIONS
-    LOGD("Layers will be composited as regions");
+    INIT_LOGD("Layers will be composited as regions");
 #endif
 }
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index afab26a..8b1caeee 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -101,8 +101,14 @@
     }
     mBitmapResources.clear();
 
+    for (size_t i = 0; i < mFilterResources.size(); i++) {
+        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
+    }
+    mFilterResources.clear();
+
     for (size_t i = 0; i < mShaders.size(); i++) {
         caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+        caches.resourceCache.destructor(mShaders.itemAt(i));
     }
     mShaders.clear();
 
@@ -151,11 +157,18 @@
         caches.resourceCache.incrementRefcount(resource);
     }
 
+    const Vector<SkiaColorFilter*> &filterResources = recorder.getFilterResources();
+    for (size_t i = 0; i < filterResources.size(); i++) {
+        SkiaColorFilter* resource = filterResources.itemAt(i);
+        mFilterResources.add(resource);
+        caches.resourceCache.incrementRefcount(resource);
+    }
+
     const Vector<SkiaShader*> &shaders = recorder.getShaders();
     for (size_t i = 0; i < shaders.size(); i++) {
-        SkiaShader* shader = shaders.itemAt(i);
-        mShaders.add(shader);
-        caches.resourceCache.incrementRefcount(shader);
+        SkiaShader* resource = shaders.itemAt(i);
+        mShaders.add(resource);
+        caches.resourceCache.incrementRefcount(resource);
     }
 
     const Vector<SkPaint*> &paints = recorder.getPaints();
@@ -686,9 +699,10 @@
                 float* vertices = getFloats(verticesCount);
                 bool hasColors = getInt();
                 int* colors = hasColors ? getInts(colorsCount) : NULL;
+                SkPaint* paint = getPaint();
 
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
-                renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
+                renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint);
             }
             break;
             case DrawPatch: {
@@ -705,9 +719,15 @@
                 yDivs = getInts(yDivsCount);
                 colors = getUInts(numColors);
 
+                float left = getFloat();
+                float top = getFloat();
+                float right = getFloat();
+                float bottom = getFloat();
+                SkPaint* paint = getPaint();
+
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
-                        numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+                        numColors, left, top, right, bottom, paint);
             }
             break;
             case DrawColor: {
@@ -786,15 +806,17 @@
             case DrawLines: {
                 int count = 0;
                 float* points = getFloats(count);
+                SkPaint* paint = getPaint();
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
-                renderer.drawLines(points, count, getPaint());
+                renderer.drawLines(points, count, paint);
             }
             break;
             case DrawPoints: {
                 int count = 0;
                 float* points = getFloats(count);
+                SkPaint* paint = getPaint();
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
-                renderer.drawPoints(points, count, getPaint());
+                renderer.drawPoints(points, count, paint);
             }
             break;
             case DrawText: {
@@ -873,21 +895,27 @@
 
     Caches& caches = Caches::getInstance();
     for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        SkBitmap* resource = mBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcount(resource);
+        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
     }
     mBitmapResources.clear();
 
+    for (size_t i = 0; i < mFilterResources.size(); i++) {
+        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
+    }
+    mFilterResources.clear();
+
     for (size_t i = 0; i < mShaders.size(); i++) {
-       caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
     }
     mShaders.clear();
     mShaderMap.clear();
 
     mPaints.clear();
     mPaintMap.clear();
+
     mPaths.clear();
     mPathMap.clear();
+
     mMatrices.clear();
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index dcf2cf2..b83259f 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -292,6 +292,10 @@
         return mBitmapResources;
     }
 
+    const Vector<SkiaColorFilter*>& getFilterResources() const {
+        return mFilterResources;
+    }
+
     const Vector<SkiaShader*>& getShaders() const {
         return mShaders;
     }
@@ -308,10 +312,6 @@
         return mMatrices;
     }
 
-    const Vector<SkiaColorFilter*>& getFilterResources() const {
-        return mFilterResources;
-    }
-
 private:
     void insertRestoreToCount() {
         if (mRestoreSaveCount >= 0) {
@@ -419,7 +419,9 @@
     inline void addMatrix(SkMatrix* matrix) {
         // Copying the matrix is cheap and prevents against the user changing the original
         // matrix before the operation that uses it
-        addInt((int) new SkMatrix(*matrix));
+        SkMatrix* copy = new SkMatrix(*matrix);
+        addInt((int) copy);
+        mMatrices.add(copy);
     }
 
     inline void addBitmap(SkBitmap* bitmap) {
@@ -429,8 +431,7 @@
         // which doesn't seem worth the extra cycles for this unlikely case.
         addInt((int) bitmap);
         mBitmapResources.add(bitmap);
-        Caches& caches = Caches::getInstance();
-        caches.resourceCache.incrementRefcount(bitmap);
+        Caches::getInstance().resourceCache.incrementRefcount(bitmap);
     }
 
     inline void addShader(SkiaShader* shader) {
@@ -454,8 +455,7 @@
     inline void addColorFilter(SkiaColorFilter* colorFilter) {
         addInt((int) colorFilter);
         mFilterResources.add(colorFilter);
-        Caches& caches = Caches::getInstance();
-        caches.resourceCache.incrementRefcount(colorFilter);
+        Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
     }
 
     Vector<SkBitmap*> mBitmapResources;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 77e63d7..e034a868 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -166,30 +166,6 @@
 // Layers management
 ///////////////////////////////////////////////////////////////////////////////
 
-Layer* LayerRenderer::createTextureLayer() {
-    LAYER_RENDERER_LOGD("Creating new texture layer");
-
-    Layer* layer = new Layer(0, 0);
-    layer->isCacheable = false;
-    layer->isTextureLayer = true;
-    layer->blend = true;
-    layer->empty = true;
-    layer->fbo = 0;
-    layer->colorFilter = NULL;
-    layer->fbo = 0;
-    layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
-    layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
-    layer->alpha = 255;
-    layer->mode = SkXfermode::kSrcOver_Mode;
-    layer->colorFilter = NULL;
-    layer->region.clear();
-
-    glActiveTexture(GL_TEXTURE0);
-    glGenTextures(1, &layer->texture);
-
-    return layer;
-}
-
 Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
     LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
 
@@ -269,24 +245,56 @@
     return true;
 }
 
+static void setTextureParameters(Layer* layer) {
+    glBindTexture(layer->renderTarget, layer->texture);
+
+    glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
+    LAYER_RENDERER_LOGD("Creating new texture layer");
+
+    Layer* layer = new Layer(0, 0);
+    layer->isCacheable = false;
+    layer->isTextureLayer = true;
+    layer->blend = !isOpaque;
+    layer->empty = true;
+    layer->fbo = 0;
+    layer->colorFilter = NULL;
+    layer->fbo = 0;
+    layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
+    layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
+    layer->alpha = 255;
+    layer->mode = SkXfermode::kSrcOver_Mode;
+    layer->colorFilter = NULL;
+    layer->region.clear();
+    layer->renderTarget = GL_NONE; // see ::updateTextureLayer()
+
+    glActiveTexture(GL_TEXTURE0);
+    glGenTextures(1, &layer->texture);
+
+    return layer;
+}
+
 void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-        GLenum renderTarget, float* transform) {
+        bool isOpaque, GLenum renderTarget, float* transform) {
     if (layer) {
+        layer->blend = !isOpaque;
         layer->width = width;
         layer->height = height;
         layer->layer.set(0.0f, 0.0f, width, height);
         layer->region.set(width, height);
         layer->regionRect.set(0.0f, 0.0f, width, height);
         layer->texTransform.load(transform);
-        layer->renderTarget = renderTarget;
 
-        glBindTexture(layer->renderTarget, layer->texture);
-
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        if (renderTarget != layer->renderTarget) {
+            layer->renderTarget = renderTarget;
+            setTextureParameters(layer);
+        }
     }
 }
 
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 797dfc6..2246573 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -55,11 +55,11 @@
     Region* getRegion();
     GLint getTargetFbo();
 
-    static Layer* createTextureLayer();
+    static Layer* createTextureLayer(bool isOpaque);
     static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
     static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
     static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-            GLenum renderTarget, float* transform);
+            bool isOpaque, GLenum renderTarget, float* transform);
     static void destroyLayer(Layer* layer);
     static void destroyLayerDeferred(Layer* layer);
     static bool copyLayer(Layer* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 88774c6..1c06a0b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -639,7 +639,7 @@
     setupDrawTextureTransform();
     setupDrawColor(alpha, alpha, alpha, alpha);
     setupDrawColorFilter();
-    setupDrawBlending(layer->blend, layer->mode);
+    setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode);
     setupDrawProgram();
     setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
     setupDrawPureColorUniforms();
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 9aade51..cd2c405 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -48,9 +48,6 @@
 
 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
     Mutex::Autolock _l(mLock);
-    for (size_t i = 0; i < mCache->size(); ++i) {
-        void* ref = mCache->valueAt(i);
-    }
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL || mCache->size() == 0) {
         ref = new ResourceReference(resourceType);
@@ -144,7 +141,6 @@
     ref->destroyed = true;
     if (ref->refCount == 0) {
         deleteResourceReference(resource, ref);
-        return;
     }
 }
 
@@ -162,7 +158,6 @@
     ref->destroyed = true;
     if (ref->refCount == 0) {
         deleteResourceReference(resource, ref);
-        return;
     }
 }
 
@@ -180,7 +175,6 @@
     ref->destroyed = true;
     if (ref->refCount == 0) {
         deleteResourceReference(resource, ref);
-        return;
     }
 }
 
@@ -195,7 +189,6 @@
     ref->destroyed = true;
     if (ref->refCount == 0) {
         deleteResourceReference(resource, ref);
-        return;
     }
 }
 
@@ -209,36 +202,32 @@
     }
     if (ref->destroyed) {
         switch (ref->resourceType) {
-            case kBitmap:
-            {
-                SkBitmap* bitmap = (SkBitmap*)resource;
+            case kBitmap: {
+                SkBitmap* bitmap = (SkBitmap*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().textureCache.removeDeferred(bitmap);
                 }
                 delete bitmap;
             }
             break;
-            case kPath:
-            {
-                SkPath* path = (SkPath*)resource;
+            case kPath: {
+                SkPath* path = (SkPath*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().pathCache.removeDeferred(path);
                 }
                 delete path;
             }
             break;
-            case kShader:
-            {
-                SkiaShader* shader = (SkiaShader*)resource;
+            case kShader: {
+                SkiaShader* shader = (SkiaShader*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader());
                 }
                 delete shader;
             }
             break;
-            case kColorFilter:
-            {
-                SkiaColorFilter* filter = (SkiaColorFilter*)resource;
+            case kColorFilter: {
+                SkiaColorFilter* filter = (SkiaColorFilter*) resource;
                 delete filter;
             }
             break;
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
index bf45e13..1bf475c 100644
--- a/libs/hwui/SkiaColorFilter.h
+++ b/libs/hwui/SkiaColorFilter.h
@@ -59,7 +59,7 @@
         return mType;
     }
 
-    SkColorFilter *getSkColorFilter() {
+    SkColorFilter* getSkColorFilter() {
         return mSkFilter;
     }
 
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
index 01a0cf6..17dd931 100644
--- a/libs/rs/driver/rsdAllocation.cpp
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -460,8 +460,8 @@
         uint8_t *srcPtr = getOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
         memcpy(dstPtr, srcPtr, w * elementSize);
 
-        LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
-             dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
+        //LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
+        //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
     }
 }
 
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index 25302aa..2f9f410 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -525,10 +525,6 @@
 //                 ::= d  # double
 
 static RsdSymbolTable gSyms[] = {
-    { "__divsi3", (void *)&SC_divsi3, true },
-    { "__modsi3", (void *)&SC_modsi3, true },
-    { "__udivsi3", (void *)&SC_udivsi3, true },
-    { "__umodsi3", (void *)&SC_umodsi3, true },
     { "memset", (void *)&memset, true },
     { "memcpy", (void *)&memcpy, true },
 
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f9990bb..427bbba 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,7 +43,6 @@
 LOCAL_SRC_FILES:= \
 	$(commonSources) \
 	EGLUtils.cpp \
-	EventRecurrence.cpp \
 	FramebufferNativeWindow.cpp \
 	GraphicBuffer.cpp \
 	GraphicBufferAllocator.cpp \
diff --git a/libs/ui/EventRecurrence.cpp b/libs/ui/EventRecurrence.cpp
deleted file mode 100644
index b436b50..0000000
--- a/libs/ui/EventRecurrence.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- *  Copyright 2006 The Android Open Source Project
- */
-
-#include <pim/EventRecurrence.h>
-#include <utils/String8.h>
-#include <stdio.h>
-#include <limits.h>
-
-namespace android {
-
-#define FAIL_HERE() do { \
-            printf("Parsing failed at line %d\n", __LINE__); \
-            return UNKNOWN_ERROR; \
-        } while(0)
-
-EventRecurrence::EventRecurrence()
-    :freq((freq_t)0),
-     until(),
-     count(0),
-     interval(0),
-     bysecond(0),
-     bysecondCount(0),
-     byminute(0),
-     byminuteCount(0),
-     byhour(0),
-     byhourCount(0),
-     byday(0),
-     bydayNum(0),
-     bydayCount(0),
-     bymonthday(0),
-     bymonthdayCount(0),
-     byyearday(0),
-     byyeardayCount(0),
-     byweekno(0),
-     byweeknoCount(0),
-     bymonth(0),
-     bymonthCount(0),
-     bysetpos(0),
-     bysetposCount(0),
-     wkst(0)
-{
-}
-
-EventRecurrence::~EventRecurrence()
-{
-    delete[] bysecond;
-    delete[] byminute;
-    delete[] byhour;
-    delete[] byday;
-    delete[] bydayNum;
-    delete[] byyearday;
-    delete[] bymonthday;
-    delete[] byweekno;
-    delete[] bymonth;
-    delete[] bysetpos;
-}
-
-enum LHS {
-    NONE_LHS = 0,
-    FREQ,
-    UNTIL,
-    COUNT,
-    INTERVAL,
-    BYSECOND,
-    BYMINUTE,
-    BYHOUR,
-    BYDAY,
-    BYMONTHDAY,
-    BYYEARDAY,
-    BYWEEKNO,
-    BYMONTH,
-    BYSETPOS,
-    WKST
-};
-
-struct LHSProc
-{
-    const char16_t* text;
-    size_t textSize;
-    uint32_t value;
-};
-
-const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' };
-const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' };
-const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' };
-const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'};
-const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' };
-const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' };
-const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' };
-const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' };
-const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' };
-const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' };
-const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' };
-const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' };
-const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' };
-const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' };
-
-#define SIZ(x) (sizeof(x)/sizeof(x[0]))
-
-const LHSProc LHSPROC[] = {
-    { FREQ_text, SIZ(FREQ_text), FREQ },
-    { UNTIL_text, SIZ(UNTIL_text), UNTIL },
-    { COUNT_text, SIZ(COUNT_text), COUNT },
-    { INTERVAL_text, SIZ(INTERVAL_text), INTERVAL },
-    { BYSECOND_text, SIZ(BYSECOND_text), BYSECOND },
-    { BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE },
-    { BYHOUR_text, SIZ(BYHOUR_text), BYHOUR },
-    { BYDAY_text, SIZ(BYDAY_text), BYDAY },
-    { BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY },
-    { BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY },
-    { BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO },
-    { BYMONTH_text, SIZ(BYMONTH_text), BYMONTH },
-    { BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS },
-    { WKST_text, SIZ(WKST_text), WKST },
-    { NULL, 0, NONE_LHS },
-};
-
-const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' };
-const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' };
-const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' };
-const char16_t DAILY_text[] = { 'D','A','I','L','Y' };
-const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' };
-const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' };
-const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' };
-
-typedef LHSProc FreqProc;
-
-const FreqProc FREQPROC[] = {
-    { SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY },
-    { MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY },
-    { HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY },
-    { DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY },
-    { WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY },
-    { MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY },
-    { YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY },
-    { NULL, 0, NONE_LHS },
-};
-
-const char16_t SU_text[] = { 'S','U' };
-const char16_t MO_text[] = { 'M','O' };
-const char16_t TU_text[] = { 'T','U' };
-const char16_t WE_text[] = { 'W','E' };
-const char16_t TH_text[] = { 'T','H' };
-const char16_t FR_text[] = { 'F','R' };
-const char16_t SA_text[] = { 'S','A' };
-
-const FreqProc WEEKDAYPROC[] = {
-    { SU_text, SIZ(SU_text), EventRecurrence::SU },
-    { MO_text, SIZ(MO_text), EventRecurrence::MO },
-    { TU_text, SIZ(TU_text), EventRecurrence::TU },
-    { WE_text, SIZ(WE_text), EventRecurrence::WE },
-    { TH_text, SIZ(TH_text), EventRecurrence::TH },
-    { FR_text, SIZ(FR_text), EventRecurrence::FR },
-    { SA_text, SIZ(SA_text), EventRecurrence::SA },
-    { NULL, 0, NONE_LHS },
-};
-
-// returns the index into LHSPROC for the match or -1 if not found
-inline static int
-match_proc(const LHSProc* p, const char16_t* str, size_t len)
-{
-    int i = 0;
-    while (p->text != NULL) {
-        if (p->textSize == len) {
-            if (0 == memcmp(p->text, str, len*sizeof(char16_t))) {
-                return i;
-            }
-        }
-        p++;
-        i++;
-    }
-    return -1;
-}
-
-// rangeMin and rangeMax are inclusive
-static status_t
-parse_int(const char16_t* str, size_t len, int* out,
-            int rangeMin, int rangeMax, bool zeroOK)
-{
-    char16_t c;
-    size_t i=0;
-
-    if (len == 0) {
-        FAIL_HERE();
-    }
-    bool negative = false;
-    c = str[0];
-    if (c == '-' ) {
-        negative = true;
-        i++;
-    }
-    else if (c == '+') {
-        i++;
-    }
-    int n = 0;
-    for (; i<len; i++) {
-        c = str[i];
-        if (c < '0' || c > '9') {
-            FAIL_HERE();
-        }
-        int prev = n;
-        n *= 10;
-        // the spec doesn't address how big these numbers can be,
-        // so we're not going to worry about not being able to represent
-        // INT_MIN, and if we're going to wrap, we'll just clamp to
-        // INT_MAX instead
-        if (n < prev) {
-            n = INT_MAX;
-        } else {
-            n += c - '0';
-        }
-    }
-    if (negative) {
-        n = -n;
-    }
-    if (n < rangeMin || n > rangeMax) {
-        FAIL_HERE();
-    }
-    if (!zeroOK && n == 0) {
-        FAIL_HERE();
-    }
-    *out = n;
-    return NO_ERROR;
-}
-
-static status_t
-parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut,
-          int rangeMin, int rangeMax, bool zeroOK,
-          status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int)
-{
-    status_t err;
-
-    if (len == 0) {
-        *countOut = 0;
-        *listOut = NULL;
-        return NO_ERROR;
-    }
-
-    // make one pass through looking for commas so we know how big to make our
-    // out array.
-    int count = 1;
-    for (size_t i=0; i<len; i++) {
-        if (str[i] == ',') {
-            count++;
-        }
-    }
-
-    int* list = new int[count];
-    const char16_t* p = str;
-    int commaIndex = 0;
-    size_t i;
-
-    for (i=0; i<len; i++) {
-        if (str[i] == ',') {
-            err = func(p, (str+i-p), list+commaIndex, rangeMin,
-                    rangeMax, zeroOK);
-            if (err != NO_ERROR) {
-                goto bail;
-            }
-            commaIndex++;
-            p = str+i+1;
-        }
-    }
-
-    err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK);
-    if (err != NO_ERROR) {
-        goto bail;
-    }
-    commaIndex++;
-
-    *countOut = count;
-    *listOut = list;
-
-    return NO_ERROR;
-
-bail:
-    delete[] list;
-    FAIL_HERE();
-}
-
-// the numbers here are small, so we pack them both into one value, and then
-// split it out later.  it lets us reuse all the comma separated list code.
-static status_t
-parse_byday(const char16_t* s, size_t len, int* out,
-            int rangeMin, int rangeMax, bool zeroOK)
-{
-    status_t err;
-    int n = 0;
-    const char16_t* p = s;
-    size_t plen = len;
-
-    if (len > 0) {
-        char16_t c = s[0];
-        if (c == '-' || c == '+' || (c >= '0' && c <= '9')) {
-            if (len > 1) {
-                size_t nlen = 0;
-                c = s[nlen];
-                while (nlen < len
-                        && (c == '-' || c == '+' || (c >= '0' && c <= '9'))) {
-                    c = s[nlen];
-                    nlen++;
-                }
-                if (nlen > 0) {
-                    nlen--;
-                    err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK);
-                    if (err != NO_ERROR) {
-                        FAIL_HERE();
-                    }
-                    p += nlen;
-                    plen -= nlen;
-                }
-            }
-        }
-
-        int index = match_proc(WEEKDAYPROC, p, plen);
-        if (index >= 0) {
-            *out = (0xffff0000 & WEEKDAYPROC[index].value)
-                    | (0x0000ffff & n);
-            return NO_ERROR;
-        }
-    }
-    return UNKNOWN_ERROR;
-}
-
-static void
-postprocess_byday(int count, int* byday, int** bydayNum)
-{
-    int* bdn = new int[count];
-    *bydayNum = bdn;
-    for (int i=0; i<count; i++) {
-        uint32_t v = byday[i];
-        int16_t num = v & 0x0000ffff;
-        byday[i] = v & 0xffff0000;  
-        // will sign extend:
-        bdn[i] = num;
-    }
-}
-
-#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \
-    if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \
-                         &name##Count, &name, rangeMin, rangeMax, zeroOK)) { \
-        FAIL_HERE(); \
-    }
-status_t
-EventRecurrence::parse(const String16& str)
-{
-    char16_t const* work = str.string();
-    size_t len = str.size();
-
-    int lhsIndex = NONE_LHS;
-    int index;
-    
-    size_t start = 0;
-    for (size_t i=0; i<len; i++) {
-        char16_t c = work[i];
-        if (c != ';' && i == len-1) {
-            c = ';';
-            i++;
-        }
-        if (c == ';' || c == '=') {
-            if (i != start) {
-                const char16_t* s = work+start;
-                const size_t slen = i-start;
-
-                String8 thestring(String16(s, slen));
-
-                switch (c)
-                {
-                    case '=':
-                        if (lhsIndex == NONE_LHS) {
-                            lhsIndex = match_proc(LHSPROC, s, slen);
-                            if (lhsIndex >= 0) {
-                                break;
-                            }
-                        }
-                        FAIL_HERE();
-                    case ';':
-                    {
-                        switch (LHSPROC[lhsIndex].value)
-                        {
-                            case FREQ:
-                                if (this->freq != 0) {
-                                    FAIL_HERE();
-                                }
-                                index = match_proc(FREQPROC, s, slen);
-                                if (index >= 0) {
-                                    this->freq = (freq_t)FREQPROC[index].value;
-                                }
-                                break;
-                            case UNTIL:
-                                // XXX should check that this is a valid time
-                                until.setTo(String16(s, slen));
-                                break;
-                            case COUNT:
-                                if (count != 0
-                                     || NO_ERROR != parse_int(s, slen,
-                                             &count, INT_MIN, INT_MAX, true)) {
-                                    FAIL_HERE();
-                                }
-                                break;
-                            case INTERVAL:
-                                if (interval != 0
-                                     || NO_ERROR != parse_int(s, slen,
-                                         &interval, INT_MIN, INT_MAX, false)) {
-                                    FAIL_HERE();
-                                }
-                                break;
-                            case BYSECOND:
-                                PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true)
-                                break;
-                            case BYMINUTE:
-                                PARSE_INT_LIST_CHECKED(byminute, 0, 59, true)
-                                break;
-                            case BYHOUR:
-                                PARSE_INT_LIST_CHECKED(byhour, 0, 23, true)
-                                break;
-                            case BYDAY:
-                                if (bydayCount != 0 || NO_ERROR != 
-                                        parse_int_list(s, slen, &bydayCount,
-                                              &byday, -53, 53, false,
-                                              parse_byday)) {
-                                    FAIL_HERE();
-                                }
-                                postprocess_byday(bydayCount, byday, &bydayNum);
-                                break;
-                            case BYMONTHDAY:
-                                PARSE_INT_LIST_CHECKED(bymonthday, -31, 31,
-                                                        false)
-                                break;
-                            case BYYEARDAY:
-                                PARSE_INT_LIST_CHECKED(byyearday, -366, 366,
-                                                        false)
-                                break;
-                            case BYWEEKNO:
-                                PARSE_INT_LIST_CHECKED(byweekno, -53, 53,
-                                                        false)
-                                break;
-                            case BYMONTH:
-                                PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false)
-                                break;
-                            case BYSETPOS:
-                                PARSE_INT_LIST_CHECKED(bysetpos,
-                                                        INT_MIN, INT_MAX, true)
-                                break;
-                            case WKST:
-                                if (this->wkst != 0) {
-                                    FAIL_HERE();
-                                }
-                                index = match_proc(WEEKDAYPROC, s, slen);
-                                if (index >= 0) {
-                                    this->wkst = (int)WEEKDAYPROC[index].value;
-                                }
-                                break;
-                            default:
-                                FAIL_HERE();
-                        }
-                        lhsIndex = NONE_LHS;
-                        break;
-                    }
-                }
-
-                start = i+1;
-            }
-        }
-    }
-
-    // enforce that there was a FREQ
-    if (freq == 0) {
-        FAIL_HERE();
-    }
-
-    // default wkst to MO if it wasn't specified
-    if (wkst == 0) {
-        wkst = MO;
-    }
-
-    return NO_ERROR;
-}
-
-
-}; // namespace android
-
-
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index ffdfe66..c46d6f4 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -443,7 +443,8 @@
 
     if (! mPinned || ! mMotionEventSampleDataTail) {
         LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
-                "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
+                "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
+                mChannel->getName().string());
         return INVALID_OPERATION;
     }
 
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 093189c..774e8c9 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -27,6 +27,7 @@
 	Debug.cpp \
 	FileMap.cpp \
 	Flattenable.cpp \
+	LinearTransform.cpp \
 	ObbFile.cpp \
 	Pool.cpp \
 	PropertyMap.cpp \
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index f963058..87912639 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -285,7 +285,8 @@
             break;
         }
         default:
-            LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
+            LOGD("Chunk header at %d has invalid type: 0x%08x",
+                    (int)(m_pos - sizeof(m_header)), (int)m_header.type);
             m_status = EINVAL;
     }
     
diff --git a/libs/utils/LinearTransform.cpp b/libs/utils/LinearTransform.cpp
new file mode 100644
index 0000000..d752415
--- /dev/null
+++ b/libs/utils/LinearTransform.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <utils/LinearTransform.h>
+
+namespace android {
+
+template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+
+// Static math methods involving linear transformations
+static bool scale_u64_to_u64(
+        uint64_t val,
+        uint32_t N,
+        uint32_t D,
+        uint64_t* res,
+        bool round_up_not_down) {
+    uint64_t tmp1, tmp2;
+    uint32_t r;
+
+    assert(res);
+    assert(D);
+
+    // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
+    // integer X.
+    // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
+    // integer X.
+    // Let X[A, B] with A <= B denote bits A through B of the integer X.
+    // Let (A | B) denote the concatination of two 32 bit ints, A and B.
+    // IOW X = (A | B) => U32(X) == A && L32(X) == B
+    //
+    // compute M = val * N (a 96 bit int)
+    // ---------------------------------
+    // tmp2 = U32(val) * N (a 64 bit int)
+    // tmp1 = L32(val) * N (a 64 bit int)
+    // which means
+    // M = val * N = (tmp2 << 32) + tmp1
+    tmp2 = (val >> 32) * N;
+    tmp1 = (val & UINT32_MAX) * N;
+
+    // compute M[32, 95]
+    // tmp2 = tmp2 + U32(tmp1)
+    //      = (U32(val) * N) + U32(L32(val) * N)
+    //      = M[32, 95]
+    tmp2 += tmp1 >> 32;
+
+    // if M[64, 95] >= D, then M/D has bits > 63 set and we have
+    // an overflow.
+    if ((tmp2 >> 32) >= D) {
+        *res = UINT64_MAX;
+        return false;
+    }
+
+    // Divide.  Going in we know
+    // tmp2 = M[32, 95]
+    // U32(tmp2) < D
+    r = tmp2 % D;
+    tmp2 /= D;
+
+    // At this point
+    // tmp1      = L32(val) * N
+    // tmp2      = M[32, 95] / D
+    //           = (M / D)[32, 95]
+    // r         = M[32, 95] % D
+    // U32(tmp2) = 0
+    //
+    // compute tmp1 = (r | M[0, 31])
+    tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
+
+    // Divide again.  Keep the remainder around in order to round properly.
+    r = tmp1 % D;
+    tmp1 /= D;
+
+    // At this point
+    // tmp2      = (M / D)[32, 95]
+    // tmp1      = (M / D)[ 0, 31]
+    // r         =  M % D
+    // U32(tmp1) = 0
+    // U32(tmp2) = 0
+
+    // Pack the result and deal with the round-up case (As well as the
+    // remote possiblility over overflow in such a case).
+    *res = (tmp2 << 32) | tmp1;
+    if (r && round_up_not_down) {
+        ++(*res);
+        if (!(*res)) {
+            *res = UINT64_MAX;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static bool linear_transform_s64_to_s64(
+        int64_t  val,
+        int64_t  basis1,
+        int32_t  N,
+        uint32_t D,
+        int64_t  basis2,
+        int64_t* out) {
+    uint64_t scaled, res;
+    uint64_t abs_val;
+    bool is_neg;
+
+    if (!out)
+        return false;
+
+    // Compute abs(val - basis_64). Keep track of whether or not this delta
+    // will be negative after the scale opertaion.
+    if (val < basis1) {
+        is_neg = true;
+        abs_val = basis1 - val;
+    } else {
+        is_neg = false;
+        abs_val = val - basis1;
+    }
+
+    if (N < 0)
+        is_neg = !is_neg;
+
+    if (!scale_u64_to_u64(abs_val,
+                          ABS(N),
+                          D,
+                          &scaled,
+                          is_neg))
+        return false; // overflow/undeflow
+
+    // if scaled is >= 0x8000<etc>, then we are going to overflow or
+    // underflow unless ABS(basis2) is large enough to pull us back into the
+    // non-overflow/underflow region.
+    if (scaled & INT64_MIN) {
+        if (is_neg && (basis2 < 0))
+            return false; // certain underflow
+
+        if (!is_neg && (basis2 >= 0))
+            return false; // certain overflow
+
+        if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
+            return false; // not enough
+
+        // Looks like we are OK
+        *out = (is_neg ? (-scaled) : scaled) + basis2;
+    } else {
+        // Scaled fits within signed bounds, so we just need to check for
+        // over/underflow for two signed integers.  Basically, if both scaled
+        // and basis2 have the same sign bit, and the result has a different
+        // sign bit, then we have under/overflow.  An easy way to compute this
+        // is
+        // (scaled_signbit XNOR basis_signbit) &&
+        // (scaled_signbit XOR res_signbit)
+        // ==
+        // (scaled_signbit XOR basis_signbit XOR 1) &&
+        // (scaled_signbit XOR res_signbit)
+
+        if (is_neg)
+            scaled = -scaled;
+        res = scaled + basis2;
+
+        if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
+            return false;
+
+        *out = res;
+    }
+
+    return true;
+}
+
+bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
+    if (0 == a_to_b_denom)
+        return false;
+
+    return linear_transform_s64_to_s64(a_in,
+                                       a_zero,
+                                       a_to_b_numer,
+                                       a_to_b_denom,
+                                       b_zero,
+                                       b_out);
+}
+
+bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
+    if (0 == a_to_b_numer)
+        return false;
+
+    return linear_transform_s64_to_s64(b_in,
+                                       b_zero,
+                                       a_to_b_denom,
+                                       a_to_b_numer,
+                                       a_zero,
+                                       a_out);
+}
+
+template <class T> void LinearTransform::reduce(T* N, T* D) {
+    T a, b;
+    if (!N || !D || !(*D)) {
+        assert(false);
+        return;
+    }
+
+    a = *N;
+    b = *D;
+
+    if (a == 0) {
+        *D = 1;
+        return;
+    }
+
+    // This implements Euclid's method to find GCD.
+    if (a < b) {
+        T tmp = a;
+        a = b;
+        b = tmp;
+    }
+
+    while (1) {
+        // a is now the greater of the two.
+        const T remainder = a % b;
+        if (remainder == 0) {
+            *N /= b;
+            *D /= b;
+            return;
+        }
+        // by swapping remainder and b, we are guaranteeing that a is
+        // still the greater of the two upon entrance to the loop.
+        a = b;
+        b = remainder;
+    }
+};
+
+template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
+template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+
+void LinearTransform::reduce(int32_t* N, uint32_t* D) {
+    if (N && D && *D) {
+        if (*N < 0) {
+            *N = -(*N);
+            reduce(reinterpret_cast<uint32_t*>(N), D);
+            *N = -(*N);
+        } else {
+            reduce(reinterpret_cast<uint32_t*>(N), D);
+        }
+    }
+}
+
+}  // namespace android
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index 3c05403..939bd4a 100755
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Locale;
+
 /**
  * This class wraps the country information.
  *
@@ -74,7 +76,7 @@
                 || source > COUNTRY_SOURCE_LOCALE) {
             throw new IllegalArgumentException();
         }
-        mCountryIso = countryIso.toLowerCase();
+        mCountryIso = countryIso.toUpperCase(Locale.US);
         mSource = source;
     }
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2557730..33312d1 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1568,7 +1568,14 @@
                 return;
             case MEDIA_TIMED_TEXT:
                 if (mOnTimedTextListener != null) {
-                    mOnTimedTextListener.onTimedText(mMediaPlayer, (String)msg.obj);
+                    if (msg.obj == null) {
+                        mOnTimedTextListener.onTimedText(mMediaPlayer, null);
+                    } else {
+                        if (msg.obj instanceof byte[]) {
+                            TimedText text = new TimedText((byte[])(msg.obj));
+                            mOnTimedTextListener.onTimedText(mMediaPlayer, text);
+                        }
+                    }
                 }
                 return;
 
@@ -1755,14 +1762,14 @@
     public interface OnTimedTextListener
     {
         /**
-         * Called to indicate the video size
+         * Called to indicate an avaliable timed text
          *
          * @param mp             the MediaPlayer associated with this callback
-         * @param text           the timed text sample which contains the
-         *                       text needed to be displayed.
+         * @param text           the timed text sample which contains the text
+         *                       needed to be displayed and the display format.
          * {@hide}
          */
-        public void onTimedText(MediaPlayer mp, String text);
+        public void onTimedText(MediaPlayer mp, TimedText text);
     }
 
     /**
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index dd45111..e3cbd57 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -16,17 +16,16 @@
 
 package android.media;
 
-import android.media.CamcorderProfile;
 import android.hardware.Camera;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
 import android.view.Surface;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
+
 import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.lang.ref.WeakReference;
 
 /**
@@ -112,7 +111,8 @@
     /**
      * Sets a Camera to use for recording. Use this function to switch
      * quickly between preview and capture mode without a teardown of
-     * the camera object. Must call before prepare().
+     * the camera object. {@link android.hardware.Camera#unlock()} should be
+     * called before this. Must call before prepare().
      *
      * @param c the Camera to use for recording
      */
@@ -718,6 +718,12 @@
      * Begins capturing and encoding data to the file specified with
      * setOutputFile(). Call this after prepare().
      *
+     * <p>Since API level 13, if applications set a camera via
+     * {@link #setCamera(Camera)}, the apps can use the camera after this method
+     * call. The apps do not need to lock the camera again. However, if this
+     * method fails, the apps should still lock the camera back. The apps should
+     * not start another recording session during recording.
+     *
      * @throws IllegalStateException if it is called before
      * prepare().
      */
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 8d408c2..591a8b9 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -32,17 +32,13 @@
    Class to hold the media's metadata.  Metadata are used
    for human consumption and can be embedded in the media (e.g
    shoutcast) or available from an external source. The source can be
-   local (e.g thumbnail stored in the DB) or remote (e.g caption
-   server).
+   local (e.g thumbnail stored in the DB) or remote.
 
    Metadata is like a Bundle. It is sparse and each key can occur at
    most once. The key is an integer and the value is the actual metadata.
 
    The caller is expected to know the type of the metadata and call
    the right get* method to fetch its value.
-
-   // FIXME: unhide.
-   {@hide}
  */
 public class Metadata
 {
@@ -59,69 +55,190 @@
     // client to make the data purge-able once it is done with it.
     //
 
+    /**
+     * {@hide}
+     */
     public static final int ANY = 0;  // Never used for metadata returned, only for filtering.
                                       // Keep in sync with kAny in MediaPlayerService.cpp
 
+    // Playback capabilities.
+    /**
+     * Indicate whether the media can be paused
+     */
+    public static final int PAUSE_AVAILABLE         = 1; // Boolean
+    /**
+     * Indicate whether the media can be backward seeked
+     */
+    public static final int SEEK_BACKWARD_AVAILABLE = 2; // Boolean
+    /**
+     * Indicate whether the media can be forward seeked
+     */
+    public static final int SEEK_FORWARD_AVAILABLE  = 3; // Boolean
+    /**
+     * Indicate whether the media can be seeked
+     */
+    public static final int SEEK_AVAILABLE          = 4; // Boolean
+
     // TODO: Should we use numbers compatible with the metadata retriever?
-    public static final int TITLE = 1;           // String
-    public static final int COMMENT = 2;         // String
-    public static final int COPYRIGHT = 3;       // String
-    public static final int ALBUM = 4;           // String
-    public static final int ARTIST = 5;          // String
-    public static final int AUTHOR = 6;          // String
-    public static final int COMPOSER = 7;        // String
-    public static final int GENRE = 8;           // String
-    public static final int DATE = 9;            // Date
-    public static final int DURATION = 10;       // Integer(millisec)
-    public static final int CD_TRACK_NUM = 11;   // Integer 1-based
-    public static final int CD_TRACK_MAX = 12;   // Integer
-    public static final int RATING = 13;         // String
-    public static final int ALBUM_ART = 14;      // byte[]
-    public static final int VIDEO_FRAME = 15;    // Bitmap
-    public static final int CAPTION = 16;        // TimedText
+    /**
+     * {@hide}
+     */
+    public static final int TITLE                   = 5; // String
+    /**
+     * {@hide}
+     */
+    public static final int COMMENT                 = 6; // String
+    /**
+     * {@hide}
+     */
+    public static final int COPYRIGHT               = 7; // String
+    /**
+     * {@hide}
+     */
+    public static final int ALBUM                   = 8; // String
+    /**
+     * {@hide}
+     */
+    public static final int ARTIST                  = 9; // String
+    /**
+     * {@hide}
+     */
+    public static final int AUTHOR                  = 10; // String
+    /**
+     * {@hide}
+     */
+    public static final int COMPOSER                = 11; // String
+    /**
+     * {@hide}
+     */
+    public static final int GENRE                   = 12; // String
+    /**
+     * {@hide}
+     */
+    public static final int DATE                    = 13; // Date
+    /**
+     * {@hide}
+     */
+    public static final int DURATION                = 14; // Integer(millisec)
+    /**
+     * {@hide}
+     */
+    public static final int CD_TRACK_NUM            = 15; // Integer 1-based
+    /**
+     * {@hide}
+     */
+    public static final int CD_TRACK_MAX            = 16; // Integer
+    /**
+     * {@hide}
+     */
+    public static final int RATING                  = 17; // String
+    /**
+     * {@hide}
+     */
+    public static final int ALBUM_ART               = 18; // byte[]
+    /**
+     * {@hide}
+     */
+    public static final int VIDEO_FRAME             = 19; // Bitmap
 
-    public static final int BIT_RATE = 17;       // Integer, Aggregate rate of
-                                                 // all the streams in bps.
+    /**
+     * {@hide}
+     */
+    public static final int BIT_RATE                = 20; // Integer, Aggregate rate of
+                                                          // all the streams in bps.
 
-    public static final int AUDIO_BIT_RATE = 18; // Integer, bps
-    public static final int VIDEO_BIT_RATE = 19; // Integer, bps
-    public static final int AUDIO_SAMPLE_RATE = 20; // Integer, Hz
-    public static final int VIDEO_FRAME_RATE = 21;  // Integer, Hz
+    /**
+     * {@hide}
+     */
+    public static final int AUDIO_BIT_RATE          = 21; // Integer, bps
+    /**
+     * {@hide}
+     */
+    public static final int VIDEO_BIT_RATE          = 22; // Integer, bps
+    /**
+     * {@hide}
+     */
+    public static final int AUDIO_SAMPLE_RATE       = 23; // Integer, Hz
+    /**
+     * {@hide}
+     */
+    public static final int VIDEO_FRAME_RATE        = 24; // Integer, Hz
 
     // See RFC2046 and RFC4281.
-    public static final int MIME_TYPE = 22;      // String
-    public static final int AUDIO_CODEC = 23;    // String
-    public static final int VIDEO_CODEC = 24;    // String
+    /**
+     * {@hide}
+     */
+    public static final int MIME_TYPE               = 25; // String
+    /**
+     * {@hide}
+     */
+    public static final int AUDIO_CODEC             = 26; // String
+    /**
+     * {@hide}
+     */
+    public static final int VIDEO_CODEC             = 27; // String
 
-    public static final int VIDEO_HEIGHT = 25;   // Integer
-    public static final int VIDEO_WIDTH = 26;    // Integer
-    public static final int NUM_TRACKS = 27;     // Integer
-    public static final int DRM_CRIPPLED = 28;   // Boolean
+    /**
+     * {@hide}
+     */
+    public static final int VIDEO_HEIGHT            = 28; // Integer
+    /**
+     * {@hide}
+     */
+    public static final int VIDEO_WIDTH             = 29; // Integer
+    /**
+     * {@hide}
+     */
+    public static final int NUM_TRACKS              = 30; // Integer
+    /**
+     * {@hide}
+     */
+    public static final int DRM_CRIPPLED            = 31; // Boolean
 
-    // Playback capabilities.
-    public static final int PAUSE_AVAILABLE = 29;         // Boolean
-    public static final int SEEK_BACKWARD_AVAILABLE = 30; // Boolean
-    public static final int SEEK_FORWARD_AVAILABLE = 31;  // Boolean
-    public static final int SEEK_AVAILABLE = 32;          // Boolean
-
-    private static final int LAST_SYSTEM = 32;
+    private static final int LAST_SYSTEM = 31;
     private static final int FIRST_CUSTOM = 8192;
 
     // Shorthands to set the MediaPlayer's metadata filter.
+    /**
+     * {@hide}
+     */
     public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET;
+    /**
+     * {@hide}
+     */
     public static final Set<Integer> MATCH_ALL = Collections.singleton(ANY);
 
+    /**
+     * {@hide}
+     */
     public static final int STRING_VAL     = 1;
+    /**
+     * {@hide}
+     */
     public static final int INTEGER_VAL    = 2;
+    /**
+     * {@hide}
+     */
     public static final int BOOLEAN_VAL    = 3;
+    /**
+     * {@hide}
+     */
     public static final int LONG_VAL       = 4;
+    /**
+     * {@hide}
+     */
     public static final int DOUBLE_VAL     = 5;
-    public static final int TIMED_TEXT_VAL = 6;
-    public static final int DATE_VAL       = 7;
-    public static final int BYTE_ARRAY_VAL = 8;
+    /**
+     * {@hide}
+     */
+    public static final int DATE_VAL       = 6;
+    /**
+     * {@hide}
+     */
+    public static final int BYTE_ARRAY_VAL = 7;
     // FIXME: misses a type for shared heap is missing (MemoryFile).
     // FIXME: misses a type for bitmaps.
-    private static final int LAST_TYPE = 8;
+    private static final int LAST_TYPE = 7;
 
     private static final String TAG = "media.Metadata";
     private static final int kInt32Size = 4;
@@ -142,28 +259,8 @@
             new HashMap<Integer, Integer>();
 
     /**
-     * Helper class to hold a triple (time, duration, text). Can be used to
-     * implement caption.
+     * {@hide}
      */
-    public class TimedText {
-        private Date mTime;
-        private int mDuration;  // millisec
-        private String mText;
-
-        public TimedText(Date time, int duration, String text) {
-            mTime = time;
-            mDuration = duration;
-            mText = text;
-        }
-
-        public String toString() {
-            StringBuilder res = new StringBuilder(80);
-            res.append(mTime).append("-").append(mDuration)
-                    .append(":").append(mText);
-            return res.toString();
-        }
-    }
-
     public Metadata() { }
 
     /**
@@ -273,6 +370,7 @@
      *               should not modify the parcel after this call (and
      *               not call recycle on it.)
      * @return false if an error occurred.
+     * {@hide}
      */
     public boolean parse(Parcel parcel) {
         if (parcel.dataAvail() < kMetaHeaderSize) {
@@ -328,36 +426,59 @@
     // Caller must make sure the key is present using the {@code has}
     // method otherwise a RuntimeException will occur.
 
+    /**
+     * {@hide}
+     */
     public String getString(final int key) {
         checkType(key, STRING_VAL);
         return mParcel.readString();
     }
 
+    /**
+     * {@hide}
+     */
     public int getInt(final int key) {
         checkType(key, INTEGER_VAL);
         return mParcel.readInt();
     }
 
+    /**
+     * Get the boolean value indicated by key
+     */
     public boolean getBoolean(final int key) {
         checkType(key, BOOLEAN_VAL);
         return mParcel.readInt() == 1;
     }
 
+    /**
+     * {@hide}
+     */
     public long getLong(final int key) {
-        checkType(key, LONG_VAL);
+        checkType(key, LONG_VAL);    /**
+     * {@hide}
+     */
         return mParcel.readLong();
     }
 
+    /**
+     * {@hide}
+     */
     public double getDouble(final int key) {
         checkType(key, DOUBLE_VAL);
         return mParcel.readDouble();
     }
 
+    /**
+     * {@hide}
+     */
     public byte[] getByteArray(final int key) {
         checkType(key, BYTE_ARRAY_VAL);
         return mParcel.createByteArray();
     }
 
+    /**
+     * {@hide}
+     */
     public Date getDate(final int key) {
         checkType(key, DATE_VAL);
         final long timeSinceEpoch = mParcel.readLong();
@@ -374,29 +495,30 @@
         }
     }
 
-    public TimedText getTimedText(final int key) {
-        checkType(key, TIMED_TEXT_VAL);
-        final Date startTime = new Date(mParcel.readLong());  // epoch
-        final int duration = mParcel.readInt();  // millisec
-
-        return new TimedText(startTime,
-                             duration,
-                             mParcel.readString());
-    }
-
-    // @return the last available system metadata id. Ids are
-    // 1-indexed.
+    /**
+     * @return the last available system metadata id. Ids are
+     *         1-indexed.
+     * {@hide}
+     */
     public static int lastSytemId() { return LAST_SYSTEM; }
 
-    // @return the first available cutom metadata id.
+    /**
+     * @return the first available cutom metadata id.
+     * {@hide}
+     */
     public static int firstCustomId() { return FIRST_CUSTOM; }
 
-    // @return the last value of known type. Types are 1-indexed.
+    /**
+     * @return the last value of known type. Types are 1-indexed.
+     * {@hide}
+     */
     public static int lastType() { return LAST_TYPE; }
 
-    // Check val is either a system id or a custom one.
-    // @param val Metadata key to test.
-    // @return true if it is in a valid range.
+    /**
+     * Check val is either a system id or a custom one.
+     * @param val Metadata key to test.
+     * @return true if it is in a valid range.
+     **/
     private boolean checkMetadataId(final int val) {
         if (val <= ANY || (LAST_SYSTEM < val && val < FIRST_CUSTOM)) {
             Log.e(TAG, "Invalid metadata ID " + val);
@@ -405,7 +527,9 @@
         return true;
     }
 
-    // Check the type of the data match what is expected.
+    /**
+     * Check the type of the data match what is expected.
+     */
     private void checkType(final int key, final int expectedType) {
         final int pos = mKeyToPosMap.get(key);
 
diff --git a/media/java/android/media/TimedText.java b/media/java/android/media/TimedText.java
new file mode 100644
index 0000000..a055c8b
--- /dev/null
+++ b/media/java/android/media/TimedText.java
@@ -0,0 +1,655 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.os.Parcel;
+import android.util.Log;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Class to hold the timed text's metadata.
+ *
+ * {@hide}
+ */
+public class TimedText
+{
+    private static final int FIRST_PUBLIC_KEY                 = 1;
+
+    // These keys must be in sync with the keys in TextDescription.h
+    public static final int KEY_DISPLAY_FLAGS                 = 1; // int
+    public static final int KEY_STYLE_FLAGS                   = 2; // int
+    public static final int KEY_BACKGROUND_COLOR_RGBA         = 3; // int
+    public static final int KEY_HIGHLIGHT_COLOR_RGBA          = 4; // int
+    public static final int KEY_SCROLL_DELAY                  = 5; // int
+    public static final int KEY_WRAP_TEXT                     = 6; // int
+    public static final int KEY_START_TIME                    = 7; // int
+    public static final int KEY_STRUCT_BLINKING_TEXT_LIST     = 8; // List<CharPos>
+    public static final int KEY_STRUCT_FONT_LIST              = 9; // List<Font>
+    public static final int KEY_STRUCT_HIGHLIGHT_LIST         = 10; // List<CharPos>
+    public static final int KEY_STRUCT_HYPER_TEXT_LIST        = 11; // List<HyperText>
+    public static final int KEY_STRUCT_KARAOKE_LIST           = 12; // List<Karaoke>
+    public static final int KEY_STRUCT_STYLE_LIST             = 13; // List<Style>
+    public static final int KEY_STRUCT_TEXT_POS               = 14; // TextPos
+    public static final int KEY_STRUCT_JUSTIFICATION          = 15; // Justification
+    public static final int KEY_STRUCT_TEXT                   = 16; // Text
+
+    private static final int LAST_PUBLIC_KEY                  = 16;
+
+    private static final int FIRST_PRIVATE_KEY                = 101;
+
+    // The following keys are used between TimedText.java and
+    // TextDescription.cpp in order to parce the Parcel.
+    private static final int KEY_GLOBAL_SETTING               = 101;
+    private static final int KEY_LOCAL_SETTING                = 102;
+    private static final int KEY_START_CHAR                   = 103;
+    private static final int KEY_END_CHAR                     = 104;
+    private static final int KEY_FONT_ID                      = 105;
+    private static final int KEY_FONT_SIZE                    = 106;
+    private static final int KEY_TEXT_COLOR_RGBA              = 107;
+
+    private static final int LAST_PRIVATE_KEY                 = 107;
+
+    private static final String TAG = "TimedText";
+
+    private Parcel mParcel = Parcel.obtain();
+    private final HashMap<Integer, Object> mKeyObjectMap =
+            new HashMap<Integer, Object>();
+
+    private int mDisplayFlags = -1;
+    private int mBackgroundColorRGBA = -1;
+    private int mHighlightColorRGBA = -1;
+    private int mScrollDelay = -1;
+    private int mWrapText = -1;
+
+    private List<CharPos> mBlinkingPosList = null;
+    private List<CharPos> mHighlightPosList = null;
+    private List<Karaoke> mKaraokeList = null;
+    private List<Font> mFontList = null;
+    private List<Style> mStyleList = null;
+    private List<HyperText> mHyperTextList = null;
+
+    private TextPos mTextPos;
+    private Justification mJustification;
+    private Text mTextStruct;
+
+    /**
+     * Helper class to hold the text length and text content of
+     * one text sample. The member variables in this class are
+     * read-only.
+     */
+    public class Text {
+        /**
+         * The byte-count of this text sample
+         */
+        public int textLen;
+
+        /**
+         * The text sample
+         */
+        public byte[] text;
+
+        public Text() { }
+    }
+
+    /**
+     * Helper class to hold the start char offset and end char offset
+     * for Blinking Text or Highlight Text. endChar is the end offset
+     * of the text (startChar + number of characters to be highlighted
+     * or blinked). The member variables in this class are read-only.
+     */
+    public class CharPos {
+        /**
+         * The offset of the start character
+         */
+        public int startChar = -1;
+
+        /**
+         * The offset of the end character
+         */
+        public int endChar = -1;
+
+        public CharPos() { }
+    }
+
+    /**
+     * Helper class to hold the box position to display the text sample.
+     * The member variables in this class are read-only.
+     */
+    public class TextPos {
+        /**
+         * The top position of the text
+         */
+        public int top = -1;
+
+        /**
+         * The left position of the text
+         */
+        public int left = -1;
+
+        /**
+         * The bottom position of the text
+         */
+        public int bottom = -1;
+
+        /**
+         * The right position of the text
+         */
+        public int right = -1;
+
+        public TextPos() { }
+    }
+
+    /**
+     * Helper class to hold the justification for text display in the text box.
+     * The member variables in this class are read-only.
+     */
+    public class Justification {
+        /**
+         * horizontalJustification  0: left, 1: centered, -1: right
+         */
+        public int horizontalJustification = -1;
+
+        /**
+         * verticalJustification  0: top, 1: centered, -1: bottom
+         */
+        public int verticalJustification = -1;
+
+        public Justification() { }
+    }
+
+    /**
+     * Helper class to hold the style information to display the text.
+     * The member variables in this class are read-only.
+     */
+    public class Style {
+        /**
+         * The offset of the start character which applys this style
+         */
+        public int startChar = -1;
+
+        /**
+         * The offset of the end character which applys this style
+         */
+        public int endChar = -1;
+
+        /**
+         * ID of the font. This ID will be used to choose the font
+         * to be used from the font list.
+         */
+        public int fontID = -1;
+
+        /**
+         * True if the characters should be bold
+         */
+        public boolean isBold = false;
+
+        /**
+         * True if the characters should be italic
+         */
+        public boolean isItalic = false;
+
+        /**
+         * True if the characters should be underlined
+         */
+        public boolean isUnderlined = false;
+
+        /**
+         * The size of the font
+         */
+        public int fontSize = -1;
+
+        /**
+         * To specify the RGBA color: 8 bits each of red, green, blue,
+         * and an alpha(transparency) value
+         */
+        public int colorRGBA = -1;
+
+        public Style() { }
+    }
+
+    /**
+     * Helper class to hold the font ID and name.
+     * The member variables in this class are read-only.
+     */
+    public class Font {
+        /**
+         * The font ID
+         */
+        public int ID = -1;
+
+        /**
+         * The font name
+         */
+        public String name;
+
+        public Font() { }
+    }
+
+    /**
+     * Helper class to hold the karaoke information.
+     * The member variables in this class are read-only.
+     */
+    public class Karaoke {
+        /**
+         * The start time (in milliseconds) to highlight the characters
+         * specified by startChar and endChar.
+         */
+        public int startTimeMs = -1;
+
+        /**
+         * The end time (in milliseconds) to highlight the characters
+         * specified by startChar and endChar.
+         */
+        public int endTimeMs = -1;
+
+        /**
+         * The offset of the start character to be highlighted
+         */
+        public int startChar = -1;
+
+        /**
+         * The offset of the end character to be highlighted
+         */
+        public int endChar = -1;
+
+        public Karaoke() { }
+    }
+
+    /**
+     * Helper class to hold the hyper text information.
+     * The member variables in this class are read-only.
+     */
+    public class HyperText {
+        /**
+         * The offset of the start character
+         */
+        public int startChar = -1;
+
+        /**
+         * The offset of the end character
+         */
+        public int endChar = -1;
+
+        /**
+         * The linked-to URL
+         */
+        public String URL;
+
+        /**
+         * The "alt" string for user display
+         */
+        public String altString;
+
+        public HyperText() { }
+    }
+
+    /**
+     * @param obj the byte array which contains the timed text.
+     * @throws IllegalArgumentExcept if parseParcel() fails.
+     * {@hide}
+     */
+    public TimedText(byte[] obj) {
+        mParcel.unmarshall(obj, 0, obj.length);
+
+        if (!parseParcel()) {
+            mKeyObjectMap.clear();
+            throw new IllegalArgumentException("parseParcel() fails");
+        }
+    }
+
+    /**
+     * Go over all the records, collecting metadata keys and fields in the
+     * Parcel. These are stored in mKeyObjectMap for application to retrieve.
+     * @return false if an error occurred during parsing. Otherwise, true.
+     */
+    private boolean parseParcel() {
+        mParcel.setDataPosition(0);
+        if (mParcel.dataAvail() == 0) {
+            return false;
+        }
+
+        int type = mParcel.readInt();
+        if (type == KEY_LOCAL_SETTING) {
+            type = mParcel.readInt();
+            if (type != KEY_START_TIME) {
+                return false;
+            }
+            int mStartTimeMs = mParcel.readInt();
+            mKeyObjectMap.put(type, mStartTimeMs);
+
+            type = mParcel.readInt();
+            if (type != KEY_STRUCT_TEXT) {
+                return false;
+            }
+
+            mTextStruct = new Text();
+            mTextStruct.textLen = mParcel.readInt();
+
+            mTextStruct.text = mParcel.createByteArray();
+            mKeyObjectMap.put(type, mTextStruct);
+
+        } else if (type != KEY_GLOBAL_SETTING) {
+            Log.w(TAG, "Invalid timed text key found: " + type);
+            return false;
+        }
+
+        while (mParcel.dataAvail() > 0) {
+            int key = mParcel.readInt();
+            if (!isValidKey(key)) {
+                Log.w(TAG, "Invalid timed text key found: " + key);
+                return false;
+            }
+
+            Object object = null;
+
+            switch (key) {
+                case KEY_STRUCT_STYLE_LIST: {
+                    readStyle();
+                    object = mStyleList;
+                    break;
+                }
+                case KEY_STRUCT_FONT_LIST: {
+                    readFont();
+                    object = mFontList;
+                    break;
+                }
+                case KEY_STRUCT_HIGHLIGHT_LIST: {
+                    readHighlight();
+                    object = mHighlightPosList;
+                    break;
+                }
+                case KEY_STRUCT_KARAOKE_LIST: {
+                    readKaraoke();
+                    object = mKaraokeList;
+                    break;
+                }
+                case KEY_STRUCT_HYPER_TEXT_LIST: {
+                    readHyperText();
+                    object = mHyperTextList;
+
+                    break;
+                }
+                case KEY_STRUCT_BLINKING_TEXT_LIST: {
+                    readBlinkingText();
+                    object = mBlinkingPosList;
+
+                    break;
+                }
+                case KEY_WRAP_TEXT: {
+                    mWrapText = mParcel.readInt();
+                    object = mWrapText;
+                    break;
+                }
+                case KEY_HIGHLIGHT_COLOR_RGBA: {
+                    mHighlightColorRGBA = mParcel.readInt();
+                    object = mHighlightColorRGBA;
+                    break;
+                }
+                case KEY_DISPLAY_FLAGS: {
+                    mDisplayFlags = mParcel.readInt();
+                    object = mDisplayFlags;
+                    break;
+                }
+                case KEY_STRUCT_JUSTIFICATION: {
+                    mJustification = new Justification();
+
+                    mJustification.horizontalJustification = mParcel.readInt();
+                    mJustification.verticalJustification = mParcel.readInt();
+
+                    object = mJustification;
+                    break;
+                }
+                case KEY_BACKGROUND_COLOR_RGBA: {
+                    mBackgroundColorRGBA = mParcel.readInt();
+                    object = mBackgroundColorRGBA;
+                    break;
+                }
+                case KEY_STRUCT_TEXT_POS: {
+                    mTextPos = new TextPos();
+
+                    mTextPos.top = mParcel.readInt();
+                    mTextPos.left = mParcel.readInt();
+                    mTextPos.bottom = mParcel.readInt();
+                    mTextPos.right = mParcel.readInt();
+
+                    object = mTextPos;
+                    break;
+                }
+                case KEY_SCROLL_DELAY: {
+                    mScrollDelay = mParcel.readInt();
+                    object = mScrollDelay;
+                    break;
+                }
+                default: {
+                    break;
+                }
+            }
+
+            if (object != null) {
+                if (mKeyObjectMap.containsKey(key)) {
+                    mKeyObjectMap.remove(key);
+                }
+                mKeyObjectMap.put(key, object);
+            }
+        }
+
+        mParcel.recycle();
+        return true;
+    }
+
+    /**
+     * To parse and store the Style list.
+     */
+    private void readStyle() {
+        Style style = new Style();
+        boolean endOfStyle = false;
+
+        while (!endOfStyle && (mParcel.dataAvail() > 0)) {
+            int key = mParcel.readInt();
+            switch (key) {
+                case KEY_START_CHAR: {
+                    style.startChar = mParcel.readInt();
+                    break;
+                }
+                case KEY_END_CHAR: {
+                    style.endChar = mParcel.readInt();
+                    break;
+                }
+                case KEY_FONT_ID: {
+                    style.fontID = mParcel.readInt();
+                    break;
+                }
+                case KEY_STYLE_FLAGS: {
+                    int flags = mParcel.readInt();
+                    // In the absence of any bits set in flags, the text
+                    // is plain. Otherwise, 1: bold, 2: italic, 4: underline
+                    style.isBold = ((flags % 2) == 1);
+                    style.isItalic = ((flags % 4) >= 2);
+                    style.isUnderlined = ((flags / 4) == 1);
+                    break;
+                }
+                case KEY_FONT_SIZE: {
+                    style.fontSize = mParcel.readInt();
+                    break;
+                }
+                case KEY_TEXT_COLOR_RGBA: {
+                    style.colorRGBA = mParcel.readInt();
+                    break;
+                }
+                default: {
+                    // End of the Style parsing. Reset the data position back
+                    // to the position before the last mParcel.readInt() call.
+                    mParcel.setDataPosition(mParcel.dataPosition() - 4);
+                    endOfStyle = true;
+                    break;
+                }
+            }
+        }
+
+        if (mStyleList == null) {
+            mStyleList = new ArrayList<Style>();
+        }
+        mStyleList.add(style);
+    }
+
+    /**
+     * To parse and store the Font list
+     */
+    private void readFont() {
+        int entryCount = mParcel.readInt();
+
+        for (int i = 0; i < entryCount; i++) {
+            Font font = new Font();
+
+            font.ID = mParcel.readInt();
+            int nameLen = mParcel.readInt();
+
+            byte[] text = mParcel.createByteArray();
+            font.name = new String(text, 0, nameLen);
+
+            if (mFontList == null) {
+                mFontList = new ArrayList<Font>();
+            }
+            mFontList.add(font);
+        }
+    }
+
+    /**
+     * To parse and store the Highlight list
+     */
+    private void readHighlight() {
+        CharPos pos = new CharPos();
+
+        pos.startChar = mParcel.readInt();
+        pos.endChar = mParcel.readInt();
+
+        if (mHighlightPosList == null) {
+            mHighlightPosList = new ArrayList<CharPos>();
+        }
+        mHighlightPosList.add(pos);
+    }
+
+    /**
+     * To parse and store the Karaoke list
+     */
+    private void readKaraoke() {
+        int entryCount = mParcel.readInt();
+
+        for (int i = 0; i < entryCount; i++) {
+            Karaoke kara = new Karaoke();
+
+            kara.startTimeMs = mParcel.readInt();
+            kara.endTimeMs = mParcel.readInt();
+            kara.startChar = mParcel.readInt();
+            kara.endChar = mParcel.readInt();
+
+            if (mKaraokeList == null) {
+                mKaraokeList = new ArrayList<Karaoke>();
+            }
+            mKaraokeList.add(kara);
+        }
+    }
+
+    /**
+     * To parse and store HyperText list
+     */
+    private void readHyperText() {
+        HyperText hyperText = new HyperText();
+
+        hyperText.startChar = mParcel.readInt();
+        hyperText.endChar = mParcel.readInt();
+
+        int len = mParcel.readInt();
+        byte[] url = mParcel.createByteArray();
+        hyperText.URL = new String(url, 0, len);
+
+        len = mParcel.readInt();
+        byte[] alt = mParcel.createByteArray();
+        hyperText.altString = new String(alt, 0, len);
+
+        if (mHyperTextList == null) {
+            mHyperTextList = new ArrayList<HyperText>();
+        }
+        mHyperTextList.add(hyperText);
+    }
+
+    /**
+     * To parse and store blinking text list
+     */
+    private void readBlinkingText() {
+        CharPos blinkingPos = new CharPos();
+
+        blinkingPos.startChar = mParcel.readInt();
+        blinkingPos.endChar = mParcel.readInt();
+
+        if (mBlinkingPosList == null) {
+            mBlinkingPosList = new ArrayList<CharPos>();
+        }
+        mBlinkingPosList.add(blinkingPos);
+    }
+
+    /**
+     * To check whether the given key is valid.
+     * @param key the key to be checked.
+     * @return true if the key is a valid one. Otherwise, false.
+     */
+    public boolean isValidKey(final int key) {
+        if (!((key >= FIRST_PUBLIC_KEY) && (key <= LAST_PUBLIC_KEY))
+                && !((key >= FIRST_PRIVATE_KEY) && (key <= LAST_PRIVATE_KEY))) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * To check whether the given key is contained in this TimedText object.
+     * @param key the key to be checked.
+     * @return true if the key is contained in this TimedText object.
+     *         Otherwise, false.
+     */
+    public boolean containsKey(final int key) {
+        if (isValidKey(key) && mKeyObjectMap.containsKey(key)) {
+            return true;
+        }
+        return false;
+    }
+    /**
+     * @return a set of the keys contained in this TimedText object.
+     */
+    public Set keySet() {
+        return mKeyObjectMap.keySet();
+    }
+
+    /**
+     * To retrieve the object associated with the key. Caller must make sure
+     * the key is present using the containsKey method otherwise a
+     * RuntimeException will occur.
+     * @param key the key used to retrieve the object.
+     * @return an object. The object could be an instanceof Integer, List, or
+     * any of the helper classes such as TextPos, Justification, and Text.
+     */
+    public Object getObject(final int key) {
+        if (containsKey(key)) {
+            return mKeyObjectMap.get(key);
+        } else {
+            throw new IllegalArgumentException("Invalid key: " + key);
+        }
+    }
+}
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 29c4b89..0d2bcd5 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -957,12 +957,8 @@
 
         public static final int FADE_FROM_BLACK = 8;
 
-        public static final int CURTAIN_OPENING = 9;
-
         public static final int FADE_TO_BLACK = 16;
 
-        public static final int CURTAIN_CLOSING = 17;
-
         public static final int EXTERNAL = 256;
 
         public static final int BLACK_AND_WHITE = 257;
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index 2105deb..649b98a 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -38,6 +38,7 @@
 import android.graphics.Rect;
 import android.media.videoeditor.MediaImageItem;
 import android.media.videoeditor.MediaItem;
+import android.media.MediaMetadataRetriever;
 import android.util.Log;
 import android.util.Xml;
 import android.view.Surface;
@@ -1833,12 +1834,32 @@
             }
 
             Bitmap projectBitmap = null;
-            try {
-                projectBitmap = mI.getThumbnail(width, height, 500);
-            } catch (IllegalArgumentException e) {
-                throw new IllegalArgumentException ("Illegal argument error creating project thumbnail");
-            } catch (IOException e) {
-                throw new IllegalArgumentException ("IO Error creating project thumbnail");
+            String filename = mI.getFilename();
+            if (mI instanceof MediaVideoItem) {
+                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+                retriever.setDataSource(filename);
+                Bitmap bitmap = retriever.getFrameAtTime();
+                retriever.release();
+                retriever = null;
+                if (bitmap == null) {
+                    String msg = "Thumbnail extraction from " +
+                                    filename + " failed";
+                    throw new IllegalArgumentException(msg);
+                }
+                // Resize the thumbnail to the target size
+                projectBitmap =
+                    Bitmap.createScaledBitmap(bitmap, width, height, true);
+            } else {
+                try {
+                    projectBitmap = mI.getThumbnail(width, height, 500);
+                } catch (IllegalArgumentException e) {
+                    String msg = "Project thumbnail extraction from " +
+                                    filename + " failed";
+                    throw new IllegalArgumentException(msg);
+                } catch (IOException e) {
+                    String msg = "IO Error creating project thumbnail";
+                    throw new IllegalArgumentException(msg);
+                }
             }
 
             try {
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 2f7d7ee..12391c8 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -158,7 +158,7 @@
     }
     sp<Camera> c = get_native_camera(env, camera, NULL);
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
-    process_media_recorder_call(env, mr->setCamera(c->remote()),
+    process_media_recorder_call(env, mr->setCamera(c->remote(), c->getRecordingProxy()),
             "java/lang/RuntimeException", "setCamera failed.");
 }
 
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index 5696433..277e16c 100755
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -144,6 +144,7 @@
     VIDEOEDIT_JAVA_CONSTANT_INIT("MP3",         M4VIDEOEDITING_kFileType_MP3),
     VIDEOEDIT_JAVA_CONSTANT_INIT("PCM",         M4VIDEOEDITING_kFileType_PCM),
     VIDEOEDIT_JAVA_CONSTANT_INIT("JPG",         M4VIDEOEDITING_kFileType_JPG),
+    VIDEOEDIT_JAVA_CONSTANT_INIT("PNG",         M4VIDEOEDITING_kFileType_PNG),
     VIDEOEDIT_JAVA_CONSTANT_INIT("M4V",         M4VIDEOEDITING_kFileType_M4V),
     VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", M4VIDEOEDITING_kFileType_Unsupported)
 };
@@ -377,9 +378,7 @@
 {
     VIDEOEDIT_JAVA_CONSTANT_INIT("NONE",            M4VSS3GPP_kVideoEffectType_None),
     VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_FROM_BLACK", M4VSS3GPP_kVideoEffectType_FadeFromBlack),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CURTAIN_OPENING", M4VSS3GPP_kVideoEffectType_CurtainOpening),
     VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_TO_BLACK",   M4VSS3GPP_kVideoEffectType_FadeToBlack),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CURTAIN_CLOSING", M4VSS3GPP_kVideoEffectType_CurtainClosing),
     VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL",        M4VSS3GPP_kVideoEffectType_External),
     VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_AND_WHITE", M4xVSS_kVideoEffectType_BlackAndWhite),
     VIDEOEDIT_JAVA_CONSTANT_INIT("PINK",            M4xVSS_kVideoEffectType_Pink),
@@ -1394,8 +1393,8 @@
             pSettings->FileType = (M4VIDEOEDITING_FileType)videoEditJava_getClipTypeJavaToC(
                                         &converted, pEnv->GetIntField(object, fieldIds.fileType));
 
-            if ( pSettings->FileType == M4VIDEOEDITING_kFileType_JPG)
-            {
+            if (( pSettings->FileType == M4VIDEOEDITING_kFileType_JPG) ||
+                 ( pSettings->FileType == M4VIDEOEDITING_kFileType_PNG)) {
                  pSettings->FileType = M4VIDEOEDITING_kFileType_ARGB8888;
             }
 
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
index 53e7de1..a8c08ac 100755
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ b/media/jni/mediaeditor/VideoEditorOsal.cpp
@@ -166,7 +166,6 @@
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE        ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INTERNAL_STATE                           ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_LUMA_FILTER_ERROR                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_CURTAIN_FILTER_ERROR                     ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR                  ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED                ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE             ),
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a41d7ab..4c4aad0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -70,7 +70,7 @@
     size <<= 1;
 
     if (audio_is_linear_pcm(format)) {
-        size /= channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? 2 : 1);
+        size /= channelCount * audio_bytes_per_sample(format);
     }
 
     *frameCount = size;
@@ -258,7 +258,7 @@
 int AudioRecord::frameSize() const
 {
     if (audio_is_linear_pcm(mFormat)) {
-        return channelCount()*((format() == AUDIO_FORMAT_PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+        return channelCount()*audio_bytes_per_sample(mFormat);
     } else {
         return sizeof(uint8_t);
     }
@@ -481,7 +481,7 @@
 {
     AutoMutex lock(mLock);
     int active;
-    status_t result;
+    status_t result = NO_ERROR;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = audioBuffer->frameCount;
     uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 37fe182..31eb97a 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -298,7 +298,7 @@
 int AudioTrack::frameSize() const
 {
     if (audio_is_linear_pcm(mFormat)) {
-        return channelCount()*((format() == AUDIO_FORMAT_PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+        return channelCount()*audio_bytes_per_sample(mFormat);
     } else {
         return sizeof(uint8_t);
     }
@@ -314,7 +314,7 @@
 void AudioTrack::start()
 {
     sp<AudioTrackThread> t = mAudioTrackThread;
-    status_t status;
+    status_t status = NO_ERROR;
 
     LOGV("start %p", this);
     if (t != 0) {
@@ -825,7 +825,7 @@
 {
     AutoMutex lock(mLock);
     int active;
-    status_t result;
+    status_t result = NO_ERROR;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = audioBuffer->frameCount;
     uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 59cd1b7..a44ef5a 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -60,12 +60,13 @@
     {
     }
 
-    status_t setCamera(const sp<ICamera>& camera)
+    status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
     {
-        LOGV("setCamera(%p)", camera.get());
+        LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeStrongBinder(camera->asBinder());
+        data.writeStrongBinder(proxy->asBinder());
         remote()->transact(SET_CAMERA, data, &reply);
         return reply.readInt32();
     }
@@ -434,7 +435,9 @@
             LOGV("SET_CAMERA");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
             sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());
-            reply->writeInt32(setCamera(camera));
+            sp<ICameraRecordingProxy> proxy =
+                interface_cast<ICameraRecordingProxy>(data.readStrongBinder());
+            reply->writeInt32(setCamera(camera, proxy));
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
index aec96f1..8eeebbb 100644
--- a/media/libmedia/Metadata.cpp
+++ b/media/libmedia/Metadata.cpp
@@ -32,7 +32,7 @@
 // All these constants below must be kept in sync with Metadata.java.
 enum MetadataId {
     FIRST_SYSTEM_ID = 1,
-    LAST_SYSTEM_ID = 32,
+    LAST_SYSTEM_ID = 31,
     FIRST_CUSTOM_ID = 8192
 };
 
@@ -43,7 +43,6 @@
     BOOLEAN_VAL,
     LONG_VAL,
     DOUBLE_VAL,
-    TIMED_TEXT_VAL,
     DATE_VAL,
     BYTE_ARRAY_VAL,
 };
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 0100a17..9e4edd0 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -28,9 +28,9 @@
 
 namespace android {
 
-status_t MediaRecorder::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
 {
-    LOGV("setCamera(%p)", camera.get());
+    LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
     if(mMediaRecorder == NULL) {
         LOGE("media recorder is not initialized yet");
         return INVALID_OPERATION;
@@ -40,7 +40,7 @@
         return INVALID_OPERATION;
     }
 
-    status_t ret = mMediaRecorder->setCamera(camera);
+    status_t ret = mMediaRecorder->setCamera(camera, proxy);
     if (OK != ret) {
         LOGV("setCamera failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 29cc019..115db1a 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -57,7 +57,8 @@
     return ok;
 }
 
-status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
+                                        const sp<ICameraRecordingProxy>& proxy)
 {
     LOGV("setCamera");
     Mutex::Autolock lock(mLock);
@@ -65,7 +66,7 @@
         LOGE("recorder is not initialized");
         return NO_INIT;
     }
-    return mRecorder->setCamera(camera);
+    return mRecorder->setCamera(camera, proxy);
 }
 
 status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index fded98e..bbca529 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -24,11 +24,13 @@
 
 class MediaRecorderBase;
 class MediaPlayerService;
+class ICameraRecordingProxy;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
 public:
-    virtual     status_t        setCamera(const sp<ICamera>& camera);
+    virtual     status_t        setCamera(const sp<ICamera>& camera,
+                                          const sp<ICameraRecordingProxy>& proxy);
     virtual     status_t        setPreviewSurface(const sp<Surface>& surface);
     virtual     status_t        setVideoSource(int vs);
     virtual     status_t        setAudioSource(int as);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 978571c..b003476 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -198,14 +198,20 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
+status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera,
+                                        const sp<ICameraRecordingProxy> &proxy) {
     LOGV("setCamera");
     if (camera == 0) {
         LOGE("camera is NULL");
         return BAD_VALUE;
     }
+    if (proxy == 0) {
+        LOGE("camera proxy is NULL");
+        return BAD_VALUE;
+    }
 
     mCamera = camera;
+    mCameraProxy = proxy;
     return OK;
 }
 
@@ -1235,15 +1241,17 @@
     videoSize.height = mVideoHeight;
     if (mCaptureTimeLapse) {
         mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
-                mCamera, mCameraId,
+                mCamera, mCameraProxy, mCameraId,
                 videoSize, mFrameRate, mPreviewSurface,
                 mTimeBetweenTimeLapseFrameCaptureUs);
         *cameraSource = mCameraSourceTimeLapse;
     } else {
         *cameraSource = CameraSource::CreateFromCamera(
-                mCamera, mCameraId, videoSize, mFrameRate,
+                mCamera, mCameraProxy, mCameraId, videoSize, mFrameRate,
                 mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
     }
+    mCamera.clear();
+    mCameraProxy.clear();
     if (*cameraSource == NULL) {
         return UNKNOWN_ERROR;
     }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index aa67aa7..cb9c406 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -27,6 +27,7 @@
 namespace android {
 
 class Camera;
+class ICameraRecordingProxy;
 class CameraSource;
 class CameraSourceTimeLapse;
 class MediaSourceSplitter;
@@ -48,7 +49,7 @@
     virtual status_t setVideoEncoder(video_encoder ve);
     virtual status_t setVideoSize(int width, int height);
     virtual status_t setVideoFrameRate(int frames_per_second);
-    virtual status_t setCamera(const sp<ICamera>& camera);
+    virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     virtual status_t setPreviewSurface(const sp<Surface>& surface);
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
@@ -66,6 +67,7 @@
 
 private:
     sp<ICamera> mCamera;
+    sp<ICameraRecordingProxy> mCameraProxy;
     sp<Surface> mPreviewSurface;
     sp<IMediaRecorderClient> mListener;
     sp<MediaWriter> mWriter, mWriterAux;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d628301..513eda8 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/NativeWindowWrapper.h>
 #include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
 
 #include <surfaceflinger/Surface.h>
 #include <gui/SurfaceTextureClient.h>
@@ -401,11 +402,22 @@
         CHECK(mem.get() != NULL);
 
         IOMX::buffer_id buffer;
-#if 0
-        err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer);
-#else
-        err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
-#endif
+
+        if (!strcasecmp(
+                    mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) {
+            if (portIndex == kPortIndexInput && i == 0) {
+                // Only log this warning once per allocation round.
+
+                LOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of "
+                     "OMX_AllocateBuffer instead of the preferred "
+                     "OMX_UseBuffer. Vendor must fix this.");
+            }
+
+            err = mOMX->allocateBufferWithBackup(
+                    mNode, portIndex, mem, &buffer);
+        } else {
+            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
+        }
 
         if (err != OK) {
             return err;
@@ -891,6 +903,7 @@
     CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
            || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
            || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+           || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
            || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
 
     return mOMX->setParameter(
@@ -1639,27 +1652,33 @@
     AString mime;
     CHECK(msg->findString("mime", &mime));
 
-    AString componentName;
-
-    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
-        componentName = "OMX.Nvidia.h264.decode";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
-        componentName = "OMX.google.aac.decoder";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
-        componentName = "OMX.Nvidia.mp3.decoder";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG2)) {
-        componentName = "OMX.Nvidia.mpeg2v.decode";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
-        componentName = "OMX.google.mpeg4.decoder";
-    } else {
-        TRESPASS();
-    }
+    Vector<String8> matchingCodecs;
+    OMXCodec::findMatchingCodecs(
+            mime.c_str(),
+            false, // createEncoder
+            NULL,  // matchComponentName
+            0,     // flags
+            &matchingCodecs);
 
     sp<CodecObserver> observer = new CodecObserver;
+    IOMX::node_id node = NULL;
 
-    IOMX::node_id node;
-    CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
-             (status_t)OK);
+    AString componentName;
+
+    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+            ++matchIndex) {
+        componentName = matchingCodecs.itemAt(matchIndex).string();
+
+        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
+
+        if (err == OK) {
+            break;
+        }
+
+        node = NULL;
+    }
+
+    CHECK(node != NULL);
 
     sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
     observer->setNotificationMessage(notify);
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 61bb2a8..ed8149a 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -115,19 +115,20 @@
     size.height = -1;
 
     sp<ICamera> camera;
-    return new CameraSource(camera, 0, size, -1, NULL, false);
+    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
 }
 
 // static
 CameraSource *CameraSource::CreateFromCamera(
     const sp<ICamera>& camera,
+    const sp<ICameraRecordingProxy>& proxy,
     int32_t cameraId,
     Size videoSize,
     int32_t frameRate,
     const sp<Surface>& surface,
     bool storeMetaDataInVideoBuffers) {
 
-    CameraSource *source = new CameraSource(camera, cameraId,
+    CameraSource *source = new CameraSource(camera, proxy, cameraId,
                     videoSize, frameRate, surface,
                     storeMetaDataInVideoBuffers);
     return source;
@@ -135,6 +136,7 @@
 
 CameraSource::CameraSource(
     const sp<ICamera>& camera,
+    const sp<ICameraRecordingProxy>& proxy,
     int32_t cameraId,
     Size videoSize,
     int32_t frameRate,
@@ -153,13 +155,15 @@
       mNumGlitches(0),
       mGlitchDurationThresholdUs(200000),
       mCollectStats(false) {
-
     mVideoSize.width  = -1;
     mVideoSize.height = -1;
 
-    mInitCheck = init(camera, cameraId,
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    mInitCheck = init(camera, proxy, cameraId,
                     videoSize, frameRate,
                     storeMetaDataInVideoBuffers);
+    if (mInitCheck != OK) releaseCamera();
+    IPCThreadState::self()->restoreCallingIdentity(token);
 }
 
 status_t CameraSource::initCheck() const {
@@ -167,24 +171,32 @@
 }
 
 status_t CameraSource::isCameraAvailable(
-    const sp<ICamera>& camera, int32_t cameraId) {
+    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+    int32_t cameraId) {
 
     if (camera == 0) {
         mCamera = Camera::connect(cameraId);
+        if (mCamera == 0) return -EBUSY;
+        // If proxy is not passed in by applications, still use the proxy of
+        // our own Camera to simplify the code.
+        mCameraRecordingProxy = mCamera->getRecordingProxy();
         mCameraFlags &= ~FLAGS_HOT_CAMERA;
     } else {
+        // We get the proxy from Camera, not ICamera. We need to get the proxy
+        // to the remote Camera owned by the application. Here mCamera is a
+        // local Camera object created by us. We cannot use the proxy from
+        // mCamera here.
         mCamera = Camera::create(camera);
+        if (mCamera == 0) return -EBUSY;
+        mCameraRecordingProxy = proxy;
         mCameraFlags |= FLAGS_HOT_CAMERA;
     }
 
-    // Is camera available?
-    if (mCamera == 0) {
-        LOGE("Camera connection could not be established.");
-        return -EBUSY;
-    }
-    if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
-        mCamera->lock();
-    }
+    mCamera->lock();
+    mDeathNotifier = new DeathNotifier();
+    // isBinderAlive needs linkToDeath to work.
+    mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
+
     return OK;
 }
 
@@ -286,7 +298,6 @@
     if (width != -1 && height != -1) {
         if (!isVideoSizeSupported(width, height, sizes)) {
             LOGE("Video dimension (%dx%d) is unsupported", width, height);
-            releaseCamera();
             return BAD_VALUE;
         }
         if (isSetVideoSizeSupportedByCamera) {
@@ -300,7 +311,6 @@
         // If one and only one of the width and height is -1
         // we reject such a request.
         LOGE("Requested video size (%dx%d) is not supported", width, height);
-        releaseCamera();
         return BAD_VALUE;
     } else {  // width == -1 && height == -1
         // Do not configure the camera.
@@ -318,7 +328,6 @@
         if (strstr(supportedFrameRates, buf) == NULL) {
             LOGE("Requested frame rate (%d) is not supported: %s",
                 frameRate, supportedFrameRates);
-            releaseCamera();
             return BAD_VALUE;
         }
 
@@ -447,15 +456,16 @@
  */
 status_t CameraSource::init(
         const sp<ICamera>& camera,
+        const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
 
     status_t err = OK;
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
 
-    if ((err  = isCameraAvailable(camera, cameraId)) != OK) {
+    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
+        LOGE("Camera connection could not be established.");
         return err;
     }
     CameraParameters params(mCamera->getParameters());
@@ -494,8 +504,6 @@
         }
     }
 
-    IPCThreadState::self()->restoreCallingIdentity(token);
-
     int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
     if (glitchDurationUs > mGlitchDurationThresholdUs) {
         mGlitchDurationThresholdUs = glitchDurationUs;
@@ -521,8 +529,14 @@
 }
 
 void CameraSource::startCameraRecording() {
-    CHECK_EQ(OK, mCamera->startRecording());
-    CHECK(mCamera->recordingEnabled());
+    // Reset the identity to the current thread because media server owns the
+    // camera and recording is started by the applications. The applications
+    // will connect to the camera in ICameraRecordingProxy::startRecording.
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    mCamera->unlock();
+    mCamera.clear();
+    IPCThreadState::self()->restoreCallingIdentity(token);
+    CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
 }
 
 status_t CameraSource::start(MetaData *meta) {
@@ -544,31 +558,33 @@
         mStartTimeUs = startTimeUs;
     }
 
-    // Call setListener first before calling startCameraRecording()
-    // to avoid recording frames being dropped.
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    mCamera->setListener(new CameraSourceListener(this));
     startCameraRecording();
-    IPCThreadState::self()->restoreCallingIdentity(token);
 
     mStarted = true;
     return OK;
 }
 
 void CameraSource::stopCameraRecording() {
-    mCamera->setListener(NULL);
-    mCamera->stopRecording();
+    mCameraRecordingProxy->stopRecording();
 }
 
 void CameraSource::releaseCamera() {
     LOGV("releaseCamera");
-    if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
-        LOGV("Camera was cold when we started, stopping preview");
-        mCamera->stopPreview();
+    if (mCamera != 0) {
+        if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
+            LOGV("Camera was cold when we started, stopping preview");
+            mCamera->stopPreview();
+            mCamera->disconnect();
+        } else {
+            // Unlock the camera so the application can lock it back.
+            mCamera->unlock();
+        }
+        mCamera.clear();
     }
-    mCamera->unlock();
-    mCamera.clear();
-    mCamera = 0;
+    if (mCameraRecordingProxy != 0) {
+        mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
+        mCameraRecordingProxy.clear();
+    }
     mCameraFlags = 0;
 }
 
@@ -578,7 +594,6 @@
     mStarted = false;
     mFrameAvailableCondition.signal();
 
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
     releaseQueuedFrames();
     while (!mFramesBeingEncoded.empty()) {
         if (NO_ERROR !=
@@ -589,7 +604,6 @@
     }
     stopCameraRecording();
     releaseCamera();
-    IPCThreadState::self()->restoreCallingIdentity(token);
 
     if (mCollectStats) {
         LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
@@ -607,8 +621,8 @@
 }
 
 void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (mCamera != NULL) {
-        mCamera->releaseRecordingFrame(frame);
+    if (mCameraRecordingProxy != NULL) {
+        mCameraRecordingProxy->releaseRecordingFrame(frame);
     }
 }
 
@@ -627,9 +641,7 @@
 }
 
 void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
     releaseRecordingFrame(frame);
-    IPCThreadState::self()->restoreCallingIdentity(token);
 }
 
 void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
@@ -669,7 +681,11 @@
         Mutex::Autolock autoLock(mLock);
         while (mStarted && mFramesReceived.empty()) {
             if (NO_ERROR !=
-                mFrameAvailableCondition.waitRelative(mLock, 3000000000LL)) {
+                mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
+                if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+                    LOGW("camera recording proxy is gone");
+                    return ERROR_END_OF_STREAM;
+                }
                 LOGW("Timed out waiting for incoming camera video frames: %lld us",
                     mLastFrameTimestampUs);
             }
@@ -745,4 +761,17 @@
     return mIsMetaDataStoredInVideoBuffers;
 }
 
+CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
+    mSource = source;
+}
+
+void CameraSource::ProxyListener::dataCallbackTimestamp(
+        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
+    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
+}
+
+void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    LOGI("Camera recording proxy died");
+}
+
 }  // namespace android
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index cc22574..fe78c46 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -39,6 +39,7 @@
 // static
 CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
         const sp<ICamera> &camera,
+        const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
@@ -46,7 +47,7 @@
         int64_t timeBetweenTimeLapseFrameCaptureUs) {
 
     CameraSourceTimeLapse *source = new
-            CameraSourceTimeLapse(camera, cameraId,
+            CameraSourceTimeLapse(camera, proxy, cameraId,
                 videoSize, videoFrameRate, surface,
                 timeBetweenTimeLapseFrameCaptureUs);
 
@@ -61,12 +62,13 @@
 
 CameraSourceTimeLapse::CameraSourceTimeLapse(
         const sp<ICamera>& camera,
+        const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
         const sp<Surface>& surface,
         int64_t timeBetweenTimeLapseFrameCaptureUs)
-    : CameraSource(camera, cameraId, videoSize, videoFrameRate, surface, true),
+    : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
       mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
       mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
       mLastTimeLapseFrameRealTimestampUs(0),
@@ -315,7 +317,7 @@
         pthread_attr_destroy(&attr);
     } else {
         LOGV("start time lapse recording using video camera");
-        CHECK_EQ(OK, mCamera->startRecording());
+        CameraSource::startCameraRecording();
     }
 }
 
@@ -337,8 +339,7 @@
         // play the recording sound.
         mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
     } else {
-        mCamera->setListener(NULL);
-        mCamera->stopRecording();
+        CameraSource::stopCameraRecording();
     }
     if (mLastReadBufferCopy) {
         mLastReadBufferCopy->release();
@@ -347,9 +348,8 @@
 }
 
 void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse &&
-        mCamera != NULL) {
-        mCamera->releaseRecordingFrame(frame);
+    if (!mUseStillCameraForTimeLapse) {
+        CameraSource::releaseRecordingFrame(frame);
     }
 }
 
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 4e4f289..02eeb40 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -466,6 +466,8 @@
 
 MPEG2TSWriter::MPEG2TSWriter(int fd)
     : mFile(fdopen(dup(fd), "wb")),
+      mWriteCookie(NULL),
+      mWriteFunc(NULL),
       mStarted(false),
       mNumSourcesDone(0),
       mNumTSPacketsWritten(0),
@@ -475,6 +477,21 @@
 
 MPEG2TSWriter::MPEG2TSWriter(const char *filename)
     : mFile(fopen(filename, "wb")),
+      mWriteCookie(NULL),
+      mWriteFunc(NULL),
+      mStarted(false),
+      mNumSourcesDone(0),
+      mNumTSPacketsWritten(0),
+      mNumTSPacketsBeforeMeta(0) {
+    init();
+}
+
+MPEG2TSWriter::MPEG2TSWriter(
+        void *cookie,
+        ssize_t (*write)(void *cookie, const void *data, size_t size))
+    : mFile(NULL),
+      mWriteCookie(cookie),
+      mWriteFunc(write),
       mStarted(false),
       mNumSourcesDone(0),
       mNumTSPacketsWritten(0),
@@ -483,7 +500,7 @@
 }
 
 void MPEG2TSWriter::init() {
-    CHECK(mFile != NULL);
+    CHECK(mFile != NULL || mWriteFunc != NULL);
 
     mLooper = new ALooper;
     mLooper->setName("MPEG2TSWriter");
@@ -502,8 +519,10 @@
     mLooper->unregisterHandler(mReflector->id());
     mLooper->stop();
 
-    fclose(mFile);
-    mFile = NULL;
+    if (mFile != NULL) {
+        fclose(mFile);
+        mFile = NULL;
+    }
 }
 
 status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
@@ -718,7 +737,7 @@
     static const unsigned kContinuityCounter = 5;
     buffer->data()[3] |= kContinuityCounter;
 
-    CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
 }
 
 void MPEG2TSWriter::writeProgramMap() {
@@ -794,7 +813,7 @@
     *ptr++ = 0x00;
     *ptr++ = 0x00;
 
-    CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
 }
 
 void MPEG2TSWriter::writeAccessUnit(
@@ -890,7 +909,7 @@
 
     memcpy(ptr, accessUnit->data(), copy);
 
-    CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
 
     size_t offset = copy;
     while (offset < accessUnit->size()) {
@@ -923,7 +942,7 @@
         }
 
         memcpy(ptr, accessUnit->data() + offset, copy);
-        CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile),
+        CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
                  buffer->size());
 
         offset += copy;
@@ -939,5 +958,13 @@
     }
 }
 
+ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
+    if (mFile != NULL) {
+        return fwrite(data, 1, size, mFile);
+    }
+
+    return (*mWriteFunc)(mWriteCookie, data, size);
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5fe511f..5582f92 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -889,11 +889,17 @@
             uint32_t entry_count = U32_AT(&buffer[4]);
 
             if (entry_count > 1) {
-                // For now we only support a single type of media per track.
-
-                mLastTrack->skipTrack = true;
-                *offset += chunk_size;
-                break;
+                // For 3GPP timed text, there could be multiple tx3g boxes contain
+                // multiple text display formats. These formats will be used to
+                // display the timed text.
+                const char *mime;
+                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+                    // For now we only support a single type of media per track.
+                    mLastTrack->skipTrack = true;
+                    *offset += chunk_size;
+                    break;
+                }
             }
 
             off64_t stop_offset = *offset + chunk_size;
@@ -1324,9 +1330,53 @@
             return parseDrmSINF(offset, data_offset);
         }
 
+        case FOURCC('h', 'd', 'l', 'r'):
+        {
+            uint32_t buffer;
+            if (mDataSource->readAt(
+                        data_offset + 8, &buffer, 4) < 4) {
+                return ERROR_IO;
+            }
+
+            uint32_t type = ntohl(buffer);
+            // For the 3GPP file format, the handler-type within the 'hdlr' box
+            // shall be 'text'
+            if (type == FOURCC('t', 'e', 'x', 't')) {
+                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+            }
+
+            *offset += chunk_size;
+            break;
+        }
+
         case FOURCC('t', 'x', '3', 'g'):
         {
-            mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+            uint32_t type;
+            const void *data;
+            size_t size = 0;
+            if (!mLastTrack->meta->findData(
+                    kKeyTextFormatData, &type, &data, &size)) {
+                size = 0;
+            }
+
+            uint8_t *buffer = new uint8_t[size + chunk_size];
+
+            if (size > 0) {
+                memcpy(buffer, data, size);
+            }
+
+            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
+                    < chunk_size) {
+                delete[] buffer;
+                buffer = NULL;
+
+                return ERROR_IO;
+            }
+
+            mLastTrack->meta->setData(
+                    kKeyTextFormatData, 0, buffer, size + chunk_size);
+
+            delete[] buffer;
 
             *offset += chunk_size;
             break;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index ea9911c..f075699d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -205,6 +205,8 @@
     // Duration is time scale based
     void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
     void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+
+    bool isTrackMalFormed() const;
     void sendTrackSummary(bool hasMultipleTracks);
 
     // Write the boxes
@@ -1975,7 +1977,6 @@
         }
 
         CHECK(timestampUs >= 0);
-
         LOGV("%s media time stamp: %lld and previous paused duration %lld",
                 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
         if (timestampUs > mTrackDurationUs) {
@@ -2082,11 +2083,10 @@
 
     }
 
-    if (mSampleSizes.empty() ||                      // no samples written
-        (!mIsAudio && mNumStssTableEntries == 0) ||  // no sync frames for video
-        (OK != checkCodecSpecificData())) {          // no codec specific data
+    if (isTrackMalFormed()) {
         err = ERROR_MALFORMED;
     }
+
     mOwner->trackProgressStatus(mTrackId, -1, err);
 
     // Last chunk
@@ -2136,6 +2136,24 @@
     return err;
 }
 
+bool MPEG4Writer::Track::isTrackMalFormed() const {
+    if (mSampleSizes.empty()) {                      // no samples written
+        LOGE("The number of recorded samples is 0");
+        return true;
+    }
+
+    if (!mIsAudio && mNumStssTableEntries == 0) {  // no sync frames for video
+        LOGE("There are no sync frames for video track");
+        return true;
+    }
+
+    if (OK != checkCodecSpecificData()) {         // no codec specific data
+        return true;
+    }
+
+    return false;
+}
+
 void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
 
     // Send track summary only if test mode is enabled.
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index bb8a8be..e36b01f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -180,6 +180,7 @@
     { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
     { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
     { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
+    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
@@ -187,12 +188,14 @@
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
+    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
+    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
@@ -387,7 +390,10 @@
         quirks |= kDefersOutputBufferAllocation;
     }
 
-    if (!strncmp(componentName, "OMX.TI.", 7)) {
+    if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.DECODER")) {
+        quirks |= kRequiresAllocateBufferOnInputPorts;
+        quirks |= kRequiresAllocateBufferOnOutputPorts;
+    } else if (!strncmp(componentName, "OMX.TI.", 7)) {
         // Apparently I must not use OMX_UseBuffer on either input or
         // output ports on any of the TI components or quote:
         // "(I) may have unexpected problem (sic) which can be timing related
@@ -1390,6 +1396,7 @@
         CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
                || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+               || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
                || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
 
         err = mOMX->setParameter(
@@ -1831,7 +1838,7 @@
         }
     }
 
-    LOGV("native_window_set_usage usage=0x%x", usage);
+    LOGV("native_window_set_usage usage=0x%lx", usage);
     err = native_window_set_usage(
             mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
     if (err != 0) {
@@ -3789,7 +3796,9 @@
 
     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
 
-    if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+    if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+        return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
+    } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
         return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
     } else if (type < 0 || (size_t)type >= numNames) {
         return "UNKNOWN";
@@ -4207,6 +4216,10 @@
                             mNode, OMX_IndexConfigCommonOutputCrop,
                             &rect, sizeof(rect));
 
+                CODEC_LOGI(
+                        "video dimensions are %ld x %ld",
+                        video_def->nFrameWidth, video_def->nFrameHeight);
+
                 if (err == OK) {
                     CHECK_GE(rect.nLeft, 0);
                     CHECK_GE(rect.nTop, 0);
@@ -4221,6 +4234,10 @@
                             rect.nTop,
                             rect.nLeft + rect.nWidth - 1,
                             rect.nTop + rect.nHeight - 1);
+
+                    CODEC_LOGI(
+                            "Crop rect is %ld x %ld @ (%ld, %ld)",
+                            rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
                 } else {
                     mOutputFormat->setRect(
                             kKeyCropRect,
@@ -4229,7 +4246,6 @@
                             video_def->nFrameHeight - 1);
                 }
             }
-
             break;
         }
 
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 26eda0c..7072d58 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -33,26 +33,25 @@
 
 #include <utils/Errors.h>
 
-/* The extractor lifetime is short - just long enough to get
- * the media sources constructed - so the shared lib needs to remain open
- * beyond the lifetime of the extractor.  So keep the handle as a global
- * rather than a member of the extractor
- */
-void *gVendorLibHandle = NULL;
-
 namespace android {
 
-static Mutex gWVMutex;
+Mutex WVMExtractor::sMutex;
+uint32_t WVMExtractor::sActiveExtractors = 0;
+void *WVMExtractor::sVendorLibHandle = NULL;
 
 WVMExtractor::WVMExtractor(const sp<DataSource> &source)
     : mDataSource(source) {
     {
-        Mutex::Autolock autoLock(gWVMutex);
-        if (gVendorLibHandle == NULL) {
-            gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
+        Mutex::Autolock autoLock(sMutex);
+
+        if (sVendorLibHandle == NULL) {
+            CHECK(sActiveExtractors == 0);
+            sVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
         }
 
-        if (gVendorLibHandle == NULL) {
+        sActiveExtractors++;
+
+        if (sVendorLibHandle == NULL) {
             LOGE("Failed to open libwvm.so");
             return;
         }
@@ -60,7 +59,7 @@
 
     typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
     GetInstanceFunc getInstanceFunc =
-        (GetInstanceFunc) dlsym(gVendorLibHandle,
+        (GetInstanceFunc) dlsym(sVendorLibHandle,
                 "_ZN7android11GetInstanceENS_2spINS_10DataSourceEEE");
 
     if (getInstanceFunc) {
@@ -72,6 +71,17 @@
 }
 
 WVMExtractor::~WVMExtractor() {
+    Mutex::Autolock autoLock(sMutex);
+
+    CHECK(sActiveExtractors > 0);
+    sActiveExtractors--;
+
+    // Close lib after last use
+    if (sActiveExtractors == 0) {
+        if (sVendorLibHandle != NULL)
+            dlclose(sVendorLibHandle);
+        sVendorLibHandle = NULL;
+    }
 }
 
 size_t WVMExtractor::countTracks() {
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index ed6846c..967f126 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -41,6 +41,7 @@
 static Mutex gNetworkThreadLock;
 static base::Thread *gNetworkThread = NULL;
 static scoped_refptr<net::URLRequestContext> gReqContext;
+static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
 
 static void InitializeNetworkThreadIfNecessary() {
     Mutex::Autolock autoLock(gNetworkThreadLock);
@@ -52,6 +53,8 @@
 
         gReqContext = new SfRequestContext;
 
+        gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
+
         net::AndroidNetworkLibrary::RegisterSharedInstance(
                 new SfNetworkLibrary);
     }
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 830d2e0..ec7bd1c 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -139,7 +139,8 @@
 }
 
 status_t SoftAVC::initDecoder() {
-    if (H264SwDecInit(&mHandle, 1) == H264SWDEC_OK) {
+    // Force decoder to output buffers in display order.
+    if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
         return OK;
     }
     return UNKNOWN_ERROR;
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 3439efd..1cc85e8 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -52,7 +52,7 @@
         kInputPortIndex   = 0,
         kOutputPortIndex  = 1,
         kNumInputBuffers  = 8,
-        kNumOutputBuffers = 16,
+        kNumOutputBuffers = 2,
     };
 
     enum EOSStatus {
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index b28d947..5cc3f78 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ColorConverter"
+#include <utils/Log.h>
+
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaErrors.h>
@@ -42,6 +46,7 @@
         case OMX_COLOR_FormatCbYCrY:
         case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
         case OMX_COLOR_FormatYUV420SemiPlanar:
+        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
             return true;
 
         default:
@@ -113,6 +118,10 @@
             err = convertYUV420SemiPlanar(src, dst);
             break;
 
+        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+            err = convertTIYUV420PackedSemiPlanar(src, dst);
+            break;
+
         default:
         {
             CHECK(!"Should not be here. Unknown color conversion.");
@@ -417,6 +426,73 @@
     return OK;
 }
 
+status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
+        const BitmapParams &src, const BitmapParams &dst) {
+    uint8_t *kAdjustedClip = initClip();
+
+    if (!((dst.mWidth & 3) == 0
+            && (src.mCropLeft & 1) == 0
+            && src.cropWidth() == dst.cropWidth()
+            && src.cropHeight() == dst.cropHeight())) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    uint32_t *dst_ptr = (uint32_t *)dst.mBits
+        + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
+    const uint8_t *src_y = (const uint8_t *)src.mBits;
+
+    const uint8_t *src_u =
+        (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
+
+    for (size_t y = 0; y < src.cropHeight(); ++y) {
+        for (size_t x = 0; x < src.cropWidth(); x += 2) {
+            signed y1 = (signed)src_y[x] - 16;
+            signed y2 = (signed)src_y[x + 1] - 16;
+
+            signed u = (signed)src_u[x & ~1] - 128;
+            signed v = (signed)src_u[(x & ~1) + 1] - 128;
+
+            signed u_b = u * 517;
+            signed u_g = -u * 100;
+            signed v_g = -v * 208;
+            signed v_r = v * 409;
+
+            signed tmp1 = y1 * 298;
+            signed b1 = (tmp1 + u_b) / 256;
+            signed g1 = (tmp1 + v_g + u_g) / 256;
+            signed r1 = (tmp1 + v_r) / 256;
+
+            signed tmp2 = y2 * 298;
+            signed b2 = (tmp2 + u_b) / 256;
+            signed g2 = (tmp2 + v_g + u_g) / 256;
+            signed r2 = (tmp2 + v_r) / 256;
+
+            uint32_t rgb1 =
+                ((kAdjustedClip[r1] >> 3) << 11)
+                | ((kAdjustedClip[g1] >> 2) << 5)
+                | (kAdjustedClip[b1] >> 3);
+
+            uint32_t rgb2 =
+                ((kAdjustedClip[r2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[b2] >> 3);
+
+            dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+        }
+
+        src_y += src.mWidth;
+
+        if (y & 1) {
+            src_u += src.mWidth;
+        }
+
+        dst_ptr += dst.mWidth / 2;
+    }
+
+    return OK;
+}
+
 uint8_t *ColorConverter::initClip() {
     static const signed kClipMin = -278;
     static const signed kClipMax = 535;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a4e8ee4..a4ca32d 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -50,6 +50,9 @@
         mCropBottom = mHeight - 1;
     }
 
+    mCropWidth = mCropRight - mCropLeft + 1;
+    mCropHeight = mCropBottom - mCropTop + 1;
+
     int32_t rotationDegrees;
     if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
         rotationDegrees = 0;
@@ -60,17 +63,18 @@
 
     switch (mColorFormat) {
         case OMX_COLOR_FormatYUV420Planar:
+        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
         {
             halFormat = HAL_PIXEL_FORMAT_YV12;
-            bufWidth = (mWidth + 1) & ~1;
-            bufHeight = (mHeight + 1) & ~1;
+            bufWidth = (mCropWidth + 1) & ~1;
+            bufHeight = (mCropHeight + 1) & ~1;
             break;
         }
 
         default:
             halFormat = HAL_PIXEL_FORMAT_RGB_565;
-            bufWidth = mWidth;
-            bufHeight = mHeight;
+            bufWidth = mCropWidth;
+            bufHeight = mCropHeight;
 
             mConverter = new ColorConverter(
                     mColorFormat, OMX_COLOR_Format16bitRGB565);
@@ -79,8 +83,8 @@
     }
 
     CHECK(mNativeWindow != NULL);
-    CHECK(mWidth > 0);
-    CHECK(mHeight > 0);
+    CHECK(mCropWidth > 0);
+    CHECK(mCropHeight > 0);
     CHECK(mConverter == NULL || mConverter->isValid());
 
     CHECK_EQ(0,
@@ -109,14 +113,6 @@
         CHECK_EQ(0, native_window_set_buffers_transform(
                     mNativeWindow.get(), transform));
     }
-
-    android_native_rect_t crop;
-    crop.left = mCropLeft;
-    crop.top = mCropTop;
-    crop.right = mCropRight + 1;
-    crop.bottom = mCropBottom + 1;
-
-    CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
 }
 
 SoftwareRenderer::~SoftwareRenderer() {
@@ -142,7 +138,7 @@
 
     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
 
-    Rect bounds(mWidth, mHeight);
+    Rect bounds(mCropWidth, mCropHeight);
 
     void *dst;
     CHECK_EQ(0, mapper.lock(
@@ -152,13 +148,11 @@
         mConverter->convert(
                 data,
                 mWidth, mHeight,
-                0, 0, mWidth - 1, mHeight - 1,
+                mCropLeft, mCropTop, mCropRight, mCropBottom,
                 dst,
                 buf->stride, buf->height,
-                0, 0, mWidth - 1, mHeight - 1);
-    } else {
-        CHECK_EQ(mColorFormat, OMX_COLOR_FormatYUV420Planar);
-
+                0, 0, mCropWidth - 1, mCropHeight - 1);
+    } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
         const uint8_t *src_y = (const uint8_t *)data;
         const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
         const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
@@ -170,22 +164,57 @@
         uint8_t *dst_v = dst_y + dst_y_size;
         uint8_t *dst_u = dst_v + dst_c_size;
 
-        for (int y = 0; y < mHeight; ++y) {
-            memcpy(dst_y, src_y, mWidth);
+        for (int y = 0; y < mCropHeight; ++y) {
+            memcpy(dst_y, src_y, mCropWidth);
 
             src_y += mWidth;
             dst_y += buf->stride;
         }
 
-        for (int y = 0; y < (mHeight + 1) / 2; ++y) {
-            memcpy(dst_u, src_u, (mWidth + 1) / 2);
-            memcpy(dst_v, src_v, (mWidth + 1) / 2);
+        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+            memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
+            memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
 
             src_u += mWidth / 2;
             src_v += mWidth / 2;
             dst_u += dst_c_stride;
             dst_v += dst_c_stride;
         }
+    } else {
+        CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
+
+        const uint8_t *src_y =
+            (const uint8_t *)data;
+
+        const uint8_t *src_uv =
+            (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
+
+        uint8_t *dst_y = (uint8_t *)dst;
+
+        size_t dst_y_size = buf->stride * buf->height;
+        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+        size_t dst_c_size = dst_c_stride * buf->height / 2;
+        uint8_t *dst_v = dst_y + dst_y_size;
+        uint8_t *dst_u = dst_v + dst_c_size;
+
+        for (int y = 0; y < mCropHeight; ++y) {
+            memcpy(dst_y, src_y, mCropWidth);
+
+            src_y += mWidth;
+            dst_y += buf->stride;
+        }
+
+        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+            size_t tmp = (mCropWidth + 1) / 2;
+            for (size_t x = 0; x < tmp; ++x) {
+                dst_u[x] = src_uv[2 * x];
+                dst_v[x] = src_uv[2 * x + 1];
+            }
+
+            src_uv += mWidth;
+            dst_u += dst_c_stride;
+            dst_v += dst_c_stride;
+        }
     }
 
     CHECK_EQ(0, mapper.unlock(buf->handle));
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index ca2578f..1ccf50d 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -109,7 +109,9 @@
     void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
     void removeActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
     void freeActiveBuffers();
-
+    status_t useGraphicBuffer2_l(
+            OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
+            OMX::buffer_id *buffer);
     static OMX_ERRORTYPE OnEvent(
             OMX_IN OMX_HANDLETYPE hComponent,
             OMX_IN OMX_PTR pAppData,
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 78037b97..8f2ea95 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -47,6 +47,7 @@
     sp<ANativeWindow> mNativeWindow;
     int32_t mWidth, mHeight;
     int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+    int32_t mCropWidth, mCropHeight;
 
     SoftwareRenderer(const SoftwareRenderer &);
     SoftwareRenderer &operator=(const SoftwareRenderer &);
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index deecd25..0817bab 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -18,6 +18,7 @@
 
 #define WVM_EXTRACTOR_H_
 
+#include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <utils/Errors.h>
 
@@ -67,6 +68,10 @@
 
     WVMExtractor(const WVMExtractor &);
     WVMExtractor &operator=(const WVMExtractor &);
+
+    static Mutex sMutex;
+    static uint32_t sActiveExtractors;
+    static void *sVendorLibHandle;
 };
 
 }  // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 8462988..12ab941 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -406,12 +406,77 @@
     return OK;
 }
 
+status_t OMXNodeInstance::useGraphicBuffer2_l(
+        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
+        OMX::buffer_id *buffer) {
+
+    // port definition
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    def.nVersion.s.nVersionMajor = 1;
+    def.nVersion.s.nVersionMinor = 0;
+    def.nVersion.s.nRevision = 0;
+    def.nVersion.s.nStep = 0;
+    def.nPortIndex = portIndex;
+    OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
+    if (err != OK)
+    {
+        LOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
+        return err;
+    }
+
+    BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+
+    OMX_BUFFERHEADERTYPE *header = NULL;
+    OMX_U8* bufferHandle = const_cast<OMX_U8*>(
+            reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
+
+    err = OMX_UseBuffer(
+            mHandle,
+            &header,
+            portIndex,
+            bufferMeta,
+            def.nBufferSize,
+            bufferHandle);
+
+    if (err != OMX_ErrorNone) {
+        LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+        delete bufferMeta;
+        bufferMeta = NULL;
+        *buffer = 0;
+        return UNKNOWN_ERROR;
+    }
+
+    CHECK_EQ(header->pBuffer, bufferHandle);
+    CHECK_EQ(header->pAppPrivate, bufferMeta);
+
+    *buffer = header;
+
+    addActiveBuffer(portIndex, *buffer);
+
+    return OK;
+}
+
+// XXX: This function is here for backwards compatibility.  Once the OMX
+// implementations have been updated this can be removed and useGraphicBuffer2
+// can be renamed to useGraphicBuffer.
 status_t OMXNodeInstance::useGraphicBuffer(
         OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
         OMX::buffer_id *buffer) {
     Mutex::Autolock autoLock(mLock);
 
+    // See if the newer version of the extension is present.
     OMX_INDEXTYPE index;
+    if (OMX_GetExtensionIndex(
+            mHandle,
+            const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
+            &index) == OMX_ErrorNone) {
+        return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
+    }
+
+    LOGW("Falling back to the deprecated useAndroidNativeBuffer support.  You "
+        "should switch to the useAndroidNativeBuffer2 extension.");
+
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(
             mHandle,
             const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index a404f1f..d4354db 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -485,24 +485,20 @@
     };
     static const MimeToURL kMimeToURL[] = {
         { "video/avc",
-          "file:///sdcard/media_api/video/H264_AAC.3gp" },
-        { "video/mp4v-es", "file:///sdcard/media_api/video/gingerkids.MP4" },
+          "file:///sdcard/media_api/video/H264_500_AAC_128.3gp" },
+        { "video/mp4v-es", "file:///sdcard/media_api/video/MPEG4_320_AAC_64.mp4" },
         { "video/3gpp",
           "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
         { "audio/3gpp",
           "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
-        { "audio/amr-wb",
-          "file:///sdcard/media_api/music/"
-          "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
+        { "audio/amr-wb", NULL },
         { "audio/mp4a-latm",
-          "file:///sdcard/media_api/video/H264_AAC.3gp" },
+          "file:///sdcard/media_api/video/H263_56_AAC_24.3gp" },
         { "audio/mpeg",
-          "file:///sdcard/media_api/music/MP3CBR.mp3" },
-        { "audio/vorbis",
-          "file:///sdcard/media_api/metaDataTestMedias/OGG/"
-          "When You Say Nothing At All.ogg" },
+          "file:///sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3" },
+        { "audio/vorbis", NULL },
         { "video/x-vnd.on2.vp8",
-          "file:///sdcard/media_api/webm/big-buck-bunny_trailer.webm" },
+          "file:///sdcard/media_api/video/big-buck-bunny_trailer.webm" },
         { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "file:///sdcard/M1F1-Alaw-AFsp.wav" },
         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
           "file:///sdcard/M1F1-mulaw-AFsp.wav" },
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index f03f7a2..fd0505e 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -301,6 +301,9 @@
 // static
 bool ASessionDescription::parseNTPRange(
         const char *s, float *npt1, float *npt2) {
+    *npt1 = 0.0f;
+    *npt2 = 0.0f;
+
     if (s[0] == '-') {
         return false;  // no start time available.
     }
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index d15d9c5..f89f8e2 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -995,10 +995,12 @@
         AString val;
         CHECK(GetAttribute(range.c_str(), "npt", &val));
 
+        bool seekable = true;
+
         float npt1, npt2;
         if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
             // This is a live stream and therefore not seekable.
-            return;
+            seekable = false;
         }
 
         i = response->mHeaders.indexOfKey("rtp-info");
@@ -1044,7 +1046,7 @@
             ++n;
         }
 
-        mSeekable = true;
+        mSeekable = seekable;
     }
 
     sp<APacketSource> getPacketSource(size_t index) {
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index 9a6062c..59d0e15 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=                 \
+        TextDescriptions.cpp      \
         TimedTextParser.cpp       \
         TimedTextPlayer.cpp
 
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
new file mode 100644
index 0000000..f9c1fe0
--- /dev/null
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -0,0 +1,385 @@
+/*
+ * 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 "TextDescriptions.h"
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+TextDescriptions::TextDescriptions() {
+}
+
+status_t TextDescriptions::getParcelOfDescriptions(
+        const uint8_t *data, ssize_t size,
+        uint32_t flags, int timeMs, Parcel *parcel) {
+    parcel->freeData();
+
+    if (flags & IN_BAND_TEXT_3GPP) {
+        if (flags & GLOBAL_DESCRIPTIONS) {
+            return extract3GPPGlobalDescriptions(data, size, parcel, 0);
+        } else if (flags & LOCAL_DESCRIPTIONS) {
+            return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0);
+        }
+    } else if (flags & OUT_OF_BAND_TEXT_SRT) {
+        if (flags & LOCAL_DESCRIPTIONS) {
+            return extractSRTLocalDescriptions(data, size, timeMs, parcel);
+        }
+    }
+
+    return ERROR_UNSUPPORTED;
+}
+
+// Parse the SRT text sample, and store the timing and text sample in a Parcel.
+// The Parcel will be sent to MediaPlayer.java through event, and will be
+// parsed in TimedText.java.
+status_t TextDescriptions::extractSRTLocalDescriptions(
+        const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel) {
+    parcel->writeInt32(KEY_LOCAL_SETTING);
+    parcel->writeInt32(KEY_START_TIME);
+    parcel->writeInt32(timeMs);
+
+    parcel->writeInt32(KEY_STRUCT_TEXT);
+    // write the size of the text sample
+    parcel->writeInt32(size);
+    // write the text sample as a byte array
+    parcel->writeInt32(size);
+    parcel->write(data, size);
+
+    return OK;
+}
+
+// Extract the local 3GPP display descriptions. 3GPP local descriptions
+// are appended to the text sample if any. The descriptions could include
+// information such as text styles, highlights, karaoke and so on. They
+// are contained in different boxes, such as 'styl' box contains text
+// styles, and 'krok' box contains karaoke timing and positions.
+status_t TextDescriptions::extract3GPPLocalDescriptions(
+        const uint8_t *data, ssize_t size,
+        int timeMs, Parcel *parcel, int depth) {
+    if (depth == 0) {
+        parcel->writeInt32(KEY_LOCAL_SETTING);
+
+        // write start time to display this text sample
+        parcel->writeInt32(KEY_START_TIME);
+        parcel->writeInt32(timeMs);
+
+        ssize_t textLen = (*data) << 8 | (*(data + 1));
+
+        // write text sample length and text sample itself
+        parcel->writeInt32(KEY_STRUCT_TEXT);
+        parcel->writeInt32(textLen);
+        parcel->writeInt32(textLen);
+        parcel->write(data + 2, textLen);
+
+        if (size > textLen) {
+            data += (textLen + 2);
+            size -= (textLen + 2);
+        } else {
+            return OK;
+        }
+    }
+
+    const uint8_t *tmpData = data;
+    ssize_t chunkSize = U32_AT(tmpData);
+    uint32_t chunkType = U32_AT(tmpData + 4);
+
+    if (chunkSize <= 0) {
+        return OK;
+    }
+
+    tmpData += 8;
+
+    switch(chunkType) {
+        // 'styl' box specifies the style of the text.
+        case FOURCC('s', 't', 'y', 'l'):
+        {
+            uint16_t count = U16_AT(tmpData);
+
+            tmpData += 2;
+
+            for (int i = 0; i < count; i++) {
+                parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+                parcel->writeInt32(KEY_START_CHAR);
+                parcel->writeInt32(U16_AT(tmpData));
+
+                parcel->writeInt32(KEY_END_CHAR);
+                parcel->writeInt32(U16_AT(tmpData + 2));
+
+                parcel->writeInt32(KEY_FONT_ID);
+                parcel->writeInt32(U16_AT(tmpData + 4));
+
+                parcel->writeInt32(KEY_STYLE_FLAGS);
+                parcel->writeInt32(*(tmpData + 6));
+
+                parcel->writeInt32(KEY_FONT_SIZE);
+                parcel->writeInt32(*(tmpData + 7));
+
+                parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+                uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+                    | *(tmpData + 10) << 8 | *(tmpData + 11);
+                parcel->writeInt32(rgba);
+
+                tmpData += 12;
+            }
+
+            break;
+        }
+        // 'krok' box. The number of highlight events is specified, and each
+        // event is specified by a starting and ending char offset and an end
+        // time for the event.
+        case FOURCC('k', 'r', 'o', 'k'):
+        {
+
+            parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);
+
+            int startTime = U32_AT(tmpData);
+            uint16_t count = U16_AT(tmpData + 4);
+            parcel->writeInt32(count);
+
+            tmpData += 6;
+            int lastEndTime = 0;
+
+            for (int i = 0; i < count; i++) {
+                parcel->writeInt32(startTime + lastEndTime);
+
+                lastEndTime = U32_AT(tmpData);
+                parcel->writeInt32(lastEndTime);
+
+                parcel->writeInt32(U16_AT(tmpData + 4));
+                parcel->writeInt32(U16_AT(tmpData + 6));
+
+                tmpData += 8;
+            }
+
+            break;
+        }
+        // 'hlit' box specifies highlighted text
+        case FOURCC('h', 'l', 'i', 't'):
+        {
+            parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);
+
+            // the start char offset to highlight
+            parcel->writeInt32(U16_AT(tmpData));
+            // the last char offset to highlight
+            parcel->writeInt32(U16_AT(tmpData + 2));
+
+            break;
+        }
+        // 'hclr' box specifies the RGBA color: 8 bits each of
+        // red, green, blue, and an alpha(transparency) value
+        case FOURCC('h', 'c', 'l', 'r'):
+        {
+            parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);
+
+            uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
+                | *(tmpData + 2) << 8 | *(tmpData + 3);
+            parcel->writeInt32(rgba);
+
+            break;
+        }
+        // 'dlay' box specifies a delay after a scroll in and/or
+        // before scroll out.
+        case FOURCC('d', 'l', 'a', 'y'):
+        {
+            parcel->writeInt32(KEY_SCROLL_DELAY);
+
+            uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
+                | *(tmpData + 2) << 8 | *(tmpData + 3);
+            parcel->writeInt32(delay);
+
+            break;
+        }
+        // 'href' box for hyper text link
+        case FOURCC('h', 'r', 'e', 'f'):
+        {
+            parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);
+
+            // the start offset of the text to be linked
+            parcel->writeInt32(U16_AT(tmpData));
+            // the end offset of the text
+            parcel->writeInt32(U16_AT(tmpData + 2));
+
+            // the number of bytes in the following URL
+            int len = *(tmpData + 4);
+            parcel->writeInt32(len);
+
+            // the linked-to URL
+            parcel->writeInt32(len);
+            parcel->write(tmpData + 5, len);
+
+            tmpData += (5 + len);
+
+            // the number of bytes in the following "alt" string
+            len = *tmpData;
+            parcel->writeInt32(len);
+
+            // an "alt" string for user display
+            parcel->writeInt32(len);
+            parcel->write(tmpData + 1, len);
+
+            break;
+        }
+        // 'tbox' box to indicate the position of the text with values
+        // of top, left, bottom and right
+        case FOURCC('t', 'b', 'o', 'x'):
+        {
+            parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+            parcel->writeInt32(U16_AT(tmpData));
+            parcel->writeInt32(U16_AT(tmpData + 2));
+            parcel->writeInt32(U16_AT(tmpData + 4));
+            parcel->writeInt32(U16_AT(tmpData + 6));
+
+            break;
+        }
+        // 'blnk' to specify the char range to be blinked
+        case FOURCC('b', 'l', 'n', 'k'):
+        {
+            parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);
+
+            // start char offset
+            parcel->writeInt32(U16_AT(tmpData));
+            // end char offset
+            parcel->writeInt32(U16_AT(tmpData + 2));
+
+            break;
+        }
+        // 'twrp' box specifies text wrap behavior. If the value if 0x00,
+        // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
+        // 0x02-0xff are reserved.
+        case FOURCC('t', 'w', 'r', 'p'):
+        {
+            parcel->writeInt32(KEY_WRAP_TEXT);
+            parcel->writeInt32(*tmpData);
+
+            break;
+        }
+        default:
+        {
+            break;
+        }
+    }
+
+    if (size > chunkSize) {
+        data += chunkSize;
+        size -= chunkSize;
+        // continue to parse next box
+        return extract3GPPLocalDescriptions(data, size, 0, parcel, 1);
+    }
+
+    return OK;
+}
+
+// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
+status_t TextDescriptions::extract3GPPGlobalDescriptions(
+        const uint8_t *data, ssize_t size, Parcel *parcel, int depth) {
+
+    ssize_t chunkSize = U32_AT(data);
+    uint32_t chunkType = U32_AT(data + 4);
+    const uint8_t *tmpData = data;
+    tmpData += 8;
+
+    if (size < chunkSize) {
+        return OK;
+    }
+
+    if (depth == 0) {
+        parcel->writeInt32(KEY_GLOBAL_SETTING);
+    }
+    switch(chunkType) {
+        case FOURCC('t', 'x', '3', 'g'):
+        {
+            tmpData += 8; // skip the first 8 bytes
+            parcel->writeInt32(KEY_DISPLAY_FLAGS);
+            parcel->writeInt32(U32_AT(tmpData));
+
+            parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
+            parcel->writeInt32(tmpData[4]);
+            parcel->writeInt32(tmpData[5]);
+
+            parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
+            uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
+                | *(tmpData + 8) << 8 | *(tmpData + 9);
+            parcel->writeInt32(rgba);
+
+            tmpData += 10;
+            parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+            parcel->writeInt32(U16_AT(tmpData));
+            parcel->writeInt32(U16_AT(tmpData + 2));
+            parcel->writeInt32(U16_AT(tmpData + 4));
+            parcel->writeInt32(U16_AT(tmpData + 6));
+
+            tmpData += 8;
+            parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+            parcel->writeInt32(KEY_START_CHAR);
+            parcel->writeInt32(U16_AT(tmpData));
+
+            parcel->writeInt32(KEY_END_CHAR);
+            parcel->writeInt32(U16_AT(tmpData + 2));
+
+            parcel->writeInt32(KEY_FONT_ID);
+            parcel->writeInt32(U16_AT(tmpData + 4));
+
+            parcel->writeInt32(KEY_STYLE_FLAGS);
+            parcel->writeInt32(*(tmpData + 6));
+
+            parcel->writeInt32(KEY_FONT_SIZE);
+            parcel->writeInt32(*(tmpData + 7));
+
+            parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+            rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+                | *(tmpData + 10) << 8 | *(tmpData + 11);
+            parcel->writeInt32(rgba);
+
+            tmpData += 12;
+            parcel->writeInt32(KEY_STRUCT_FONT_LIST);
+            uint16_t count = U16_AT(tmpData);
+            parcel->writeInt32(count);
+
+            tmpData += 2;
+            for (int i = 0; i < count; i++) {
+                // font ID
+                parcel->writeInt32(U16_AT(tmpData));
+
+                // font name length
+                parcel->writeInt32(*(tmpData + 2));
+
+                int len = *(tmpData + 2);
+
+                parcel->write(tmpData + 3, len);
+                tmpData += 3 + len;
+            }
+
+            break;
+        }
+        default:
+        {
+            break;
+        }
+    }
+
+    data += chunkSize;
+    size -= chunkSize;
+
+    if (size > 0) {
+        // continue to extract next 'tx3g'
+        return extract3GPPGlobalDescriptions(data, size, parcel, 1);
+    }
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/timedtext/TextDescriptions.h b/media/libstagefright/timedtext/TextDescriptions.h
new file mode 100644
index 0000000..01449175
--- /dev/null
+++ b/media/libstagefright/timedtext/TextDescriptions.h
@@ -0,0 +1,84 @@
+ /*
+ * 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 TEXT_DESCRIPTIONS_H_
+
+#define TEXT_DESCRIPTIONS_H_
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+class TextDescriptions {
+public:
+    enum {
+        IN_BAND_TEXT_3GPP             = 0x01,
+        OUT_OF_BAND_TEXT_SRT          = 0x02,
+
+        GLOBAL_DESCRIPTIONS           = 0x100,
+        LOCAL_DESCRIPTIONS            = 0x200,
+    };
+
+    static status_t getParcelOfDescriptions(
+            const uint8_t *data, ssize_t size,
+            uint32_t flags, int timeMs, Parcel *parcel);
+private:
+    TextDescriptions();
+
+    enum {
+        // These keys must be in sync with the keys in TimedText.java
+        KEY_DISPLAY_FLAGS                 = 1, // int
+        KEY_STYLE_FLAGS                   = 2, // int
+        KEY_BACKGROUND_COLOR_RGBA         = 3, // int
+        KEY_HIGHLIGHT_COLOR_RGBA          = 4, // int
+        KEY_SCROLL_DELAY                  = 5, // int
+        KEY_WRAP_TEXT                     = 6, // int
+        KEY_START_TIME                    = 7, // int
+        KEY_STRUCT_BLINKING_TEXT_LIST     = 8, // List<CharPos>
+        KEY_STRUCT_FONT_LIST              = 9, // List<Font>
+        KEY_STRUCT_HIGHLIGHT_LIST         = 10, // List<CharPos>
+        KEY_STRUCT_HYPER_TEXT_LIST        = 11, // List<HyperText>
+        KEY_STRUCT_KARAOKE_LIST           = 12, // List<Karaoke>
+        KEY_STRUCT_STYLE_LIST             = 13, // List<Style>
+        KEY_STRUCT_TEXT_POS               = 14, // TextPos
+        KEY_STRUCT_JUSTIFICATION          = 15, // Justification
+        KEY_STRUCT_TEXT                   = 16, // Text
+
+        KEY_GLOBAL_SETTING                = 101,
+        KEY_LOCAL_SETTING                 = 102,
+        KEY_START_CHAR                    = 103,
+        KEY_END_CHAR                      = 104,
+        KEY_FONT_ID                       = 105,
+        KEY_FONT_SIZE                     = 106,
+        KEY_TEXT_COLOR_RGBA               = 107,
+    };
+
+    static status_t extractSRTLocalDescriptions(
+            const uint8_t *data, ssize_t size,
+            int timeMs, Parcel *parcel);
+    static status_t extract3GPPGlobalDescriptions(
+            const uint8_t *data, ssize_t size,
+            Parcel *parcel, int depth);
+    static status_t extract3GPPLocalDescriptions(
+            const uint8_t *data, ssize_t size,
+            int timeMs, Parcel *parcel, int depth);
+
+    DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions);
+};
+
+}  // namespace android
+#endif  // TEXT_DESCRIPTIONS_H_
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
index 50bb16d..7c8a747 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.cpp
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <binder/IPCThreadState.h>
+
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
@@ -27,9 +28,11 @@
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/Utils.h>
+
 #include "include/AwesomePlayer.h"
 #include "TimedTextPlayer.h"
 #include "TimedTextParser.h"
+#include "TextDescriptions.h"
 
 namespace android {
 
@@ -92,10 +95,11 @@
         return BAD_VALUE;
     }
 
+    status_t err;
     if (index < mTextTrackVector.size()) { // start an in-band text
         mSource = mTextTrackVector.itemAt(index);
 
-        status_t err = mSource->start();
+        err = mSource->start();
 
         if (err != OK) {
             return err;
@@ -112,13 +116,17 @@
             mTextParser = new TimedTextParser();
         }
 
-        status_t err;
         if ((err = mTextParser->init(mOutOfBandSource, fileType)) != OK) {
             return err;
         }
         mTextType = kOutOfBandText;
     }
 
+    // send sample description format
+    if ((err = extractAndSendGlobalDescriptions()) != OK) {
+        return err;
+    }
+
     int64_t positionUs;
     mObserver->getPosition(&positionUs);
     seekTo(positionUs);
@@ -211,21 +219,17 @@
     }
     mTextEventPending = false;
 
+    if (mData.dataSize() > 0) {
+        notifyListener(MEDIA_TIMED_TEXT, &mData);
+        mData.freeData();
+    }
+
     MediaSource::ReadOptions options;
     if (mSeeking) {
         options.setSeekTo(mSeekTimeUs,
                 MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
         mSeeking = false;
 
-        if (mTextType == kInBandText) {
-            if (mTextBuffer != NULL) {
-                mTextBuffer->release();
-                mTextBuffer = NULL;
-            }
-        } else {
-            mText.clear();
-        }
-
         notifyListener(MEDIA_TIMED_TEXT); //empty text to clear the screen
     }
 
@@ -233,32 +237,12 @@
     mObserver->getPosition(&positionUs);
 
     if (mTextType == kInBandText) {
-        if (mTextBuffer != NULL) {
-            uint8_t *tmp = (uint8_t *)(mTextBuffer->data());
-            size_t len = (*tmp) << 8 | (*(tmp + 1));
-
-            notifyListener(MEDIA_TIMED_TEXT,
-                           tmp + 2,
-                           len);
-
-            mTextBuffer->release();
-            mTextBuffer = NULL;
-
-        }
-
         if (mSource->read(&mTextBuffer, &options) != OK) {
             return;
         }
 
         mTextBuffer->meta_data()->findInt64(kKeyTime, &timeUs);
     } else {
-        if (mText.size() > 0) {
-            notifyListener(MEDIA_TIMED_TEXT,
-                           mText.c_str(),
-                           mText.size());
-            mText.clear();
-        }
-
         int64_t endTimeUs;
         if (mTextParser->getText(
                     &mText, &timeUs, &endTimeUs, &options) != OK) {
@@ -266,6 +250,19 @@
         }
     }
 
+    if (timeUs > 0) {
+        extractAndAppendLocalDescriptions(timeUs);
+    }
+
+    if (mTextType == kInBandText) {
+        if (mTextBuffer != NULL) {
+            mTextBuffer->release();
+            mTextBuffer = NULL;
+        }
+    } else {
+        mText.clear();
+    }
+
     //send the text now
     if (timeUs <= positionUs + 100000ll) {
         postTextEvent();
@@ -297,7 +294,8 @@
     Mutex::Autolock autoLock(mLock);
 
     if (key == KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE) {
-        String8 uri = request.readString8();
+        const String16 uri16 = request.readString16();
+        String8 uri = String8(uri16);
         KeyedVector<String8, String8> headers;
 
         // To support local subtitle file only for now
@@ -327,21 +325,92 @@
     return INVALID_OPERATION;
 }
 
-void TimedTextPlayer::notifyListener(
-        int msg, const void *data, size_t size) {
+void TimedTextPlayer::notifyListener(int msg, const Parcel *parcel) {
     if (mListener != NULL) {
         sp<MediaPlayerBase> listener = mListener.promote();
 
         if (listener != NULL) {
-            if (size > 0) {
-                mData.freeData();
-                mData.write(data, size);
-
-                listener->sendEvent(msg, 0, 0, &mData);
+            if (parcel && (parcel->dataSize() > 0)) {
+                listener->sendEvent(msg, 0, 0, parcel);
             } else { // send an empty timed text to clear the screen
                 listener->sendEvent(msg);
             }
         }
     }
 }
+
+// Each text sample consists of a string of text, optionally with sample
+// modifier description. The modifier description could specify a new
+// text style for the string of text. These descriptions are present only
+// if they are needed. This method is used to extract the modifier
+// description and append it at the end of the text.
+status_t TimedTextPlayer::extractAndAppendLocalDescriptions(int64_t timeUs) {
+    const void *data;
+    size_t size = 0;
+    int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS;
+
+    if (mTextType == kInBandText) {
+        const char *mime;
+        CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+
+        if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+            flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+            data = mTextBuffer->data();
+            size = mTextBuffer->size();
+        } else {
+            // support 3GPP only for now
+            return ERROR_UNSUPPORTED;
+        }
+    } else {
+        data = mText.c_str();
+        size = mText.size();
+        flag |= TextDescriptions::OUT_OF_BAND_TEXT_SRT;
+    }
+
+    if ((size > 0) && (flag != TextDescriptions::LOCAL_DESCRIPTIONS)) {
+        mData.freeData();
+        return TextDescriptions::getParcelOfDescriptions(
+                (const uint8_t *)data, size, flag, timeUs / 1000, &mData);
+    }
+
+    return OK;
+}
+
+// To extract and send the global text descriptions for all the text samples
+// in the text track or text file.
+status_t TimedTextPlayer::extractAndSendGlobalDescriptions() {
+    const void *data;
+    size_t size = 0;
+    int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS;
+
+    if (mTextType == kInBandText) {
+        const char *mime;
+        CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+
+        // support 3GPP only for now
+        if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+            uint32_t type;
+            // get the 'tx3g' box content. This box contains the text descriptions
+            // used to render the text track
+            if (!mSource->getFormat()->findData(
+                        kKeyTextFormatData, &type, &data, &size)) {
+                return ERROR_MALFORMED;
+            }
+
+            flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+        }
+    }
+
+    if ((size > 0) && (flag != TextDescriptions::GLOBAL_DESCRIPTIONS)) {
+        Parcel parcel;
+        if (TextDescriptions::getParcelOfDescriptions(
+                (const uint8_t *)data, size, flag, 0, &parcel) == OK) {
+            if (parcel.dataSize() > 0) {
+                notifyListener(MEDIA_TIMED_TEXT, &parcel);
+            }
+        }
+    }
+
+    return OK;
+}
 }
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h
index 590760b..a744db5 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.h
+++ b/media/libstagefright/timedtext/TimedTextPlayer.h
@@ -103,8 +103,10 @@
     void postTextEvent(int64_t delayUs = -1);
     void cancelTextEvent();
 
-    void notifyListener(
-            int msg, const void *data = NULL, size_t size = 0);
+    void notifyListener(int msg, const Parcel *parcel = NULL);
+
+    status_t extractAndAppendLocalDescriptions(int64_t timeUs);
+    status_t extractAndSendGlobalDescriptions();
 
     DISALLOW_EVIL_CONSTRUCTORS(TimedTextPlayer);
 };
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
index 0dadaa5..5120694 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
@@ -1334,7 +1334,14 @@
     // TODO : remove TC_API_035
     @LargeTest
     public void testEffectKenBurn() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        // Test ken burn effect using a JPEG file.
+        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg");
+
+        // Test ken burn effect using a PNG file
+        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png");
+    }
+
+    private void testEffectKenBurn(final String imageItemFileName) throws Exception {
         final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
         final MediaImageItem mediaImageItem =
             mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
@@ -1350,11 +1357,14 @@
         final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
             mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
 
-        assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
+        assertNotNull("EffectKenBurns: " + imageItemFileName,
+            kbEffectOnMediaItem);
+
         mediaImageItem.addEffect(kbEffectOnMediaItem);
-        assertEquals("KenBurn Start Rect", startRect,
+        assertEquals("KenBurn Start Rect: " + imageItemFileName, startRect,
             kbEffectOnMediaItem.getStartRect());
-        assertEquals("KenBurn End Rect", endRect,
+
+        assertEquals("KenBurn End Rect: " + imageItemFileName, endRect,
             kbEffectOnMediaItem.getEndRect());
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java
index 38f598a..bfa3976 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java
@@ -277,11 +277,17 @@
     // getBoolean
     @SmallTest
     public void testGetBoolean() throws Exception {
-        writeBooleanRecord(Metadata.DRM_CRIPPLED, true);
+        writeBooleanRecord(Metadata.PAUSE_AVAILABLE, true);
+        writeBooleanRecord(Metadata.SEEK_AVAILABLE, true);
+        writeBooleanRecord(Metadata.SEEK_BACKWARD_AVAILABLE, true);
+        writeBooleanRecord(Metadata.SEEK_FORWARD_AVAILABLE, true);
         adjustSize();
         assertParse();
 
-        assertEquals(true, mMetadata.getBoolean(Metadata.DRM_CRIPPLED));
+        assertEquals(true, mMetadata.getBoolean(Metadata.PAUSE_AVAILABLE));
+        assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_AVAILABLE));
+        assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE));
+        assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE));
     }
 
     // getLong
@@ -329,19 +335,6 @@
         assertEquals(new Date(0), mMetadata.getDate(Metadata.DATE));
     }
 
-    // getTimedText
-    @SmallTest
-    public void testGetTimedText() throws Exception {
-        Date now = Calendar.getInstance().getTime();
-        writeTimedTextRecord(Metadata.CAPTION, now.getTime(),
-                             10, "Some caption");
-        adjustSize();
-        assertParse();
-
-        Metadata.TimedText caption = mMetadata.getTimedText(Metadata.CAPTION);
-        assertEquals("" + now + "-" + 10 + ":Some caption", caption.toString());
-    }
-
     // ----------------------------------------------------------------------
     // HELPERS TO APPEND RECORDS
     // ----------------------------------------------------------------------
@@ -416,17 +409,4 @@
         mParcel.writeString(tz);
         adjustSize(start);
     }
-
-    // Insert a TimedText record at the current position.
-    private void writeTimedTextRecord(int metadataId, long begin,
-                                      int duration, String text) {
-        final int start = mParcel.dataPosition();
-        mParcel.writeInt(-1);  // Placeholder for the length
-        mParcel.writeInt(metadataId);
-        mParcel.writeInt(Metadata.TIMED_TEXT_VAL);
-        mParcel.writeLong(begin);
-        mParcel.writeInt(duration);
-        mParcel.writeString(text);
-        adjustSize(start);
-    }
 }
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 26cac50..0d8ea28 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -404,7 +404,6 @@
     AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
     AMOTION_EVENT_BUTTON_BACK = 1 << 3,
     AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
-    AMOTION_EVENT_BUTTON_ERASER = 1 << 5,
 };
 
 /*
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 7775dbf..e0c38b1 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -18,7 +18,6 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
-import android.nfc.ApduList;
 import android.nfc.INfcAdapterExtras;
 import android.nfc.NfcAdapter;
 import android.os.RemoteException;
@@ -207,4 +206,21 @@
     public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
         return sEmbeddedEe;
     }
+
+    /**
+     * Authenticate the client application.
+     *
+     * Some implementations of NFC Adapter Extras may require applications
+     * to authenticate with a token, before using other methods.
+     *
+     * @param a implementation specific token
+     * @throws a {@link java.lang.SecurityException} if authentication failed
+     */
+    public void authenticate(byte[] token) {
+        try {
+            sService.authenticate(token);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+        }
+    }
 }
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
index eb2f6f8..63c2de2 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -55,6 +55,64 @@
      */
     public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
 
+    /**
+     * Broadcast action: A filtered APDU was received.
+     *
+     * <p>This happens when an APDU of interest was matched by the Nfc adapter,
+     * for instance as the result of matching an externally-configured filter.
+     *
+     * <p>The filter configuration mechanism is not currently defined.
+     *
+     * <p>Always contains the extra field {@link EXTRA_APDU_BYTES}.
+     *
+     * @hide
+     */
+    public static final String ACTION_APDU_RECEIVED =
+        "com.android.nfc_extras.action.APDU_RECEIVED";
+
+    /**
+     * Mandatory byte array extra field in {@link #ACTION_APDU_RECEIVED}.
+     *
+     * <p>Contains the bytes of the received APDU.
+     *
+     * @hide
+     */
+    public static final String EXTRA_APDU_BYTES =
+        "com.android.nfc_extras.extra.APDU_BYTES";
+
+    /**
+     * Broadcast action: An EMV card removal event was detected.
+     *
+     * @hide
+     */
+    public static final String ACTION_EMV_CARD_REMOVAL =
+        "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
+
+    /**
+     * Broadcast action: An adapter implementing MIFARE Classic via card
+     * emulation detected that a block has been accessed.
+     *
+     * <p>This may only be issued for the first block that the reader
+     * authenticates to.
+     *
+     * <p>May contain the extra field {@link #EXTRA_MIFARE_BLOCK}.
+     *
+     * @hide
+     */
+    public static final String ACTION_MIFARE_ACCESS_DETECTED =
+        "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
+
+    /**
+     * Optional integer extra field in {@link #ACTION_MIFARE_ACCESS_DETECTED}.
+     *
+     * <p>Provides the block number being accessed.  If not set, the block
+     * number being accessed is unknown.
+     *
+     * @hide
+     */
+    public static final String EXTRA_MIFARE_BLOCK =
+        "com.android.nfc_extras.extra.MIFARE_BLOCK";
+
     NfcExecutionEnvironment(NfcAdapterExtras extras) {
         mExtras = extras;
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 0c4ef7d..9469601 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -531,7 +531,12 @@
     private void restoreFileData(String filename, BackupDataInput data) {
         byte[] bytes = new byte[data.getDataSize()];
         if (bytes.length <= 0) return;
-        restoreFileData(filename, bytes, bytes.length);
+        try {
+            data.readEntityData(bytes, 0, data.getDataSize());
+            restoreFileData(filename, bytes, bytes.length);
+        } catch (IOException e) {
+            Log.w(TAG, "Unable to read file data for " + filename);
+        }
     }
 
     private void restoreFileData(String filename, byte[] bytes, int size) {
@@ -589,7 +594,12 @@
     private void restoreWifiSupplicant(String filename, BackupDataInput data) {
         byte[] bytes = new byte[data.getDataSize()];
         if (bytes.length <= 0) return;
-        restoreWifiSupplicant(filename, bytes, bytes.length);
+        try {
+            data.readEntityData(bytes, 0, data.getDataSize());
+            restoreWifiSupplicant(filename, bytes, bytes.length);
+        } catch (IOException e) {
+            Log.w(TAG, "Unable to read supplicant data");
+        }
     }
 
     private void restoreWifiSupplicant(String filename, byte[] bytes, int size) {
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
index bc127bd..a90c412 100644
--- a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
index 59af804..9d6032c 100644
--- a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
index 2c7a0d4..caa8795 100644
--- a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
index baafed6..6f456f3 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
index 175197b..e592ae6 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
index ec1feff..c1f87a7 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
index c1f9a0f..2d16eda 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
index 0ea3f40..0749413 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_off.png b/packages/SystemUI/res/drawable-hdpi/hd_off.png
new file mode 100644
index 0000000..e7246cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_on.png b/packages/SystemUI/res/drawable-hdpi/hd_on.png
new file mode 100644
index 0000000..5360d42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
index ff34a7f..cbd72fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
index eb783df..2c48c97 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
index c3e381e..165fa80 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
index d6c8a21..fd33ef3 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..a557164
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
index 728a25d..7096b73 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..48cab60
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..000af5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
index ca8656c..ac5a97b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..c345e84
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
index a4f4e87..a5a9652 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..e77dfafb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
index 299a0e7..e72fde8 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..b91be07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
index 029ea22..31e747e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..5736d46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
index 06c9921..a90dc9b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..d686787
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..7dfbc5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..8883601
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
index 2249d01..2e5dc3c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
index ca3bb5d..a8f4daa 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
index cb938fe..d23f9b7 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..6d99ba5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..13b969c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..25e7e6f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
index 47b4ba2..2a94b5d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
index b2c4d45..cb3c433 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..11ddf00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..da512e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..f2a7c6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
index 20d28da..6208581 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..18fe5be
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
index 7cb2643..ab581a1 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..0246cd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
index 3be2eef..bec75e5 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
index 88ac760..fe4d318 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png
new file mode 100644
index 0000000..d5503f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png
new file mode 100644
index 0000000..a8f2236
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png
new file mode 100644
index 0000000..b7ad39c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
index 0c40c73..c93bd8c 100644
--- a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png
new file mode 100644
index 0000000..1680887
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png b/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png
new file mode 100644
index 0000000..b436fc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
index fcf4417..ce48e0b 100644
--- a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
+++ b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
index af36ac7..f10a487 100644
--- a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
+++ b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
index 18bd8b4..55f6aa1 100644
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
index 993ccf4..19dae07 100644
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
new file mode 100644
index 0000000..8811df5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png b/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
index f313ffb..0c12103 100644
--- a/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png b/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
index 37b5fef..8fbe78e 100644
--- a/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
index 4ec771a..ddbd3d7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
old mode 100755
new mode 100644
index 2ea2609..2fa0293
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..4cabd9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..3d1e89d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..8a77137
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..dbfcfda
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..cb7a692
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..8d1b95c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..4d2b2f5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..aafc621
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..b6c7450
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..67eaebd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..14450ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..0578085
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..12a7ca8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..8ac90236
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..4debc5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..92069c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..290e34b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
index c9704fc..2538ab8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
index b37dd9f..cfc6344 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
index 818e292..02757b1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
index 95866b1..4bfb8f2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
index 1aea612..ff4e040 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
index 016b30b..71050c8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
index ec672eb..aa25d50 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
old mode 100755
new mode 100644
index 27bab73..5641b7a
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..a6b0762
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
index 0e6849b..6af7f65 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
index a86a324..29d8f7b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
index 425535e..e80265c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
index 24902d6..c7ff314 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
index 4160a95..2396c01 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
index d459ee3..5256041 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
index 7b64751..5d728e7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
index d82930c..4b0472a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
index fcad363..b216c2a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
old mode 100755
new mode 100644
index 8096846..d184206
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
index e94e146..fd2d6c1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
index 8805a40..80ceea0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
index 07545d5..cdfa661 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
index 7629cef..c8bd44f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
index 4ff7db3..ecdd61f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
index 28578c6..c7c6a92 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
index d9f7a30..795e610 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
index 505ccd4..3b012cd 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
index 783c2b6..ca435ce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
index 001eaea..63823be 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
index 2c4a07f..b16455f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
index cbae7dc..db44420 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
index 11f3a5c..d99b977 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
index eb42294..72e5d5c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
index 66fb60e..3405e1c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
index 07ea499..940be0f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
index 879c703..199e021 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
index e39767a..50cbbba 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
index 47c1fca..c571496 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
old mode 100755
new mode 100644
index ac80dce..1920d0d
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
index 61a7503..466c84c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
index f88091b..2226bab 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
index 95bb3cd..200b9a9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
index c5edf2c..5a592e3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
index 0ef4701..db40781 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
index 31b926b..6bf4841 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
old mode 100755
new mode 100644
index ed02984..f323073
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
index 0ee5b08..2650479 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
index cac7802..d00f2af 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
index ddf88be..a60e4e7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
index df6e195..00d9149 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
index 4a2f867..cddd68c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
old mode 100755
new mode 100644
index 2b4628f..e43e1a9
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
index 765cdd7..5503df1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
index a0e59cf..081233b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
index 1ef75d3..b30b240 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
index 1ef75d3..b30b240 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
index a7dc07e..d018f95 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
index f1f4c4e..c4f34cb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
index 918a476..abdb7a6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
index 6e34e66..f4806cc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
index 5b2acc6..67aeef6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
index 3664ab4..fea1863 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
index f1ff548..1bd644c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
index b4fa481..46881b2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
index 5a741bb..3dfb469 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
index 7ff375a..2506e58 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
index c8ddfce..a59c844 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
index 245677b..67f16b9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
index 6b6a6df..a59c844 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
index d17771e..2aeb84a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
index b16e436..48f6122 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index b595b60..4811a30 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
index 76332c1..1439ece 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
index 0bd3ba3..3c25920 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
index 3b8aff4..06c3369 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png
new file mode 100644
index 0000000..cac47a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 473c74a..6d115b9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
index 54e02b5..a1a712f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
index ccd32fe..43803e4 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
index 046c9a0..313f0f5 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 047e888..bff9fac 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
index 21f90b0..75def49 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
index 80f5701..8316842 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
index 1456eea..efbd535 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png
new file mode 100644
index 0000000..fabcd91
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index 3b8fb13..6f2402d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
index a2675e9..e0dca0b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
index 9a6532a..0968cdd 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
index 96a205f4..54ee2e6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..c5301a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png
new file mode 100644
index 0000000..36b7327
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
index 52e8a8e..a21c7ce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png
new file mode 100644
index 0000000..931997e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png
new file mode 100644
index 0000000..54c0a07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
index a7a3623..afec31d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
index 6429ffc6..fa8ab31 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
index 03d2147..686158b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
index 9416793..0ec7307 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png
new file mode 100644
index 0000000..4d29193
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
index 4e161c6..a2aadd92 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
index c8cba34..8349da5 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
index c0de67d..f06e5d1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
index 1647b21..c390437 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
index f5b07e6..20cf07f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
index fbb31b8..f11b58e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
index c6267a4..76170a8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
index c1f2f97..15b0992 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
index 5e42b55..97d35f3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
index 8721d5c..8bea46d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
index bd400b5..17423d2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
old mode 100755
new mode 100644
index b8feac6..6d3151d
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
index 4dab171..ae58b57 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
index 6854a2b..ad1245e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
index 9c868f1..00e5bb8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
old mode 100755
new mode 100644
index efff76c..cb67d57
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
index e3a3cec..b036a89 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
index 3a5c7e2..117ac31 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
index b9ba6d5..bdae6fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
old mode 100755
new mode 100644
index dc1ce8e..df34c27
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
index 0ad77f1..2b7d95f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index 87d1944..6e5f131 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
new file mode 100644
index 0000000..017145e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
new file mode 100644
index 0000000..7466d1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png b/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png
new file mode 100644
index 0000000..772f77d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
index 3b7c9c7..90b4baf 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
index 653acbb..bc7034a 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
index a933833..6eaf6c9 100644
--- a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
index 70f7cc2..da1b637 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
index e6dab63..374873c 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/app_icon.png b/packages/SystemUI/res/drawable-large-hdpi/app_icon.png
new file mode 100644
index 0000000..52354bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..ce01276
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..1848fcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..61a3f87
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..b6aca49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..226aaac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
index 1629575..0809456 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
index e87bcec..0e8ec073 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
index fd44002..f9d2737 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
index e455ad6..f5b2c9a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
index 6613585..eb1b18a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
index 7502a54..1abe28a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
index 5f88279..e896cbb 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
index 8c04bd61..b44123c 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
index 1309176..d0cc5794e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
index 810714e..903b03e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
index 72176ba..9578a218 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
index 82a2bf0..c5e5cda 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
index 1e6c604..0730e3e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
index 13aee06..eafed59 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
index 76c48a8..ea66c75 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/app_icon.png b/packages/SystemUI/res/drawable-large-mdpi/app_icon.png
new file mode 100644
index 0000000..001811f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..3d0fbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4362836
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..f4ccd7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..6392fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..f6ee596
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
index 73cdabe..a885aab 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
index b5a39cc..32f08c8 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
index 6de880c..0111893 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
index 2dbbfc0..a9c547e 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
index a45f011..6801953 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
index 517a6bb..3ae2537 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
index 821d00e..8a9f2e2 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
index 4cdce84..8c5c482 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
index 5226c1c..36c2cf8 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
index a845648..aee1eed 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
index 1d15587..30884a96 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
index 52d5736..ce91aa9 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
index 79a2a05..82a4f61 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
index b032594..55b6b38 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
index c4abcc9..519154d 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..a39e5e0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..ffe4546
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..a78cd14
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..a43ba99
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..cfeb769
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..b39d233
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..5e0617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..da2926f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..41fd66c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..745717b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..1deb1f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..2dce223
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..e13e73f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..6c9193b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..e9bb9c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
index 258de13..b94b144 100644
--- a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
index 258de13..b94b144 100644
--- a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
index 7417afc..3de53d8 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..9b59b05 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..b517af6 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..019f33a 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..6ce1bd3 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..0633543 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_off.png b/packages/SystemUI/res/drawable-mdpi/hd_off.png
index ad09eef..6c01b8a 100644
--- a/packages/SystemUI/res/drawable-mdpi/hd_off.png
+++ b/packages/SystemUI/res/drawable-mdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_on.png b/packages/SystemUI/res/drawable-mdpi/hd_on.png
index 1471c13..de878ef 100644
--- a/packages/SystemUI/res/drawable-mdpi/hd_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
index b08ad3b..7651331 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
index 3f88968..8a4ef86 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
index e0f67e8..ba0ca70 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
index 1a3063c4..667b13d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..6d8b923
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
index f8d7008..c33271b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..2ed5df4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..c877f72
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
index 91fd0e8..5ab09f0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..d63b42a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
index 7b54daf..14d1ca9 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..14d437e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
index 55b767f..4dbca6d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..91e1429
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
index 1e39fdc..08d60d1 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..77924f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
index accdcfd..62ca427 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..74d2590
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..1b884ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..e5711eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
index 7d381dd..45183b0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
index 954621b..8169fba 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
index 0d58c3a..6d4d55d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..6619393
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..c046f58
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..6b72be2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
index 7928104..238df06 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
index 88f0a44..ff698fb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..6cc8031
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..540af65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..268a9bf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
index d338fc0..2536d92 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..06e09e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
index c888c21..897d216 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..a11dabb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
index 70f72fa..16215bd 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
index f2d0cd9..44e3577 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
index 22d6c79..8725e58 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
index 24166da..f7225ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
index 2266d15..2dcb659 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
index 4fb1cf1..e7ed68b 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
index b389a35..e346167 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png b/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
index abde010..3370aeb 100644
--- a/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
+++ b/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recent_overlay.png b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
index 4dfa3d9..33eabb2 100644
--- a/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
+++ b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
index ad025f5..5da42a3 100644
--- a/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
+++ b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
index 7e679ed..2b8768b 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
index 621e980..0672564 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
index baf70cd..511d5c3 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png b/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
index 9cbd9fe..d9598ae 100644
--- a/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png b/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
index fa9a90c..761ef05 100644
--- a/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
index 3a50987..364cf75 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
index 5bde4e5..d7a48f2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..95a797d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6184516
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..cfbdb09
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..218a0a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..6072855
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..fdfbd33
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..99f9120
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..7903132
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..ec514af
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..3ef6ce4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..cd748efe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..5cbc673
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..2005d00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..e94765e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..31b1b25
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..f06e81f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..b544180
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
index f615835..44b4272 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
index f784e7e..83edad5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
index c77e61e..24fd220 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
index b9f721a..a409313 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
index cff969e..d4f75cb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
index d2d7ab3..115ea1a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
index 83ce6d0..13b1c23 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
index abe511f..400869e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..6234c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
index d685af8..cde53f5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
index 8c697a1..9e1f8dc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
index 9a4b807..13d9ae3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
index eb11d04..e53ddac 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
index 6e54de0..3146ebf 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
index 5bfb33b..432bb20 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
index 119067b..50756bc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
index a70cc2e..f8c4a65 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
index ea3dba7..a278ed9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
index 53221b9..14b2a21 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
index 11d44d0..8072951 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
index 9defd79..da4e7bb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
index 136576d..68330a9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
index 26ca31f..c65b1616 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
index de8c5ee..a26a05e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
index 64dbf3c..afae625 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
index 34923fb..1f88c31 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
index 506b5c6..d2a5340 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
index 163976f..9f0941a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
index a6af649..c568da6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
index 0c08e52..c22ae56 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
index 1d02edb..345f351 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
index edc9536..4f931e0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
index 8376817..2897ddb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
index ecef547..0a58322 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
index a7c48b6..3a9af15 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
index f4bcd9a..260634a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
index b46bb3a..2521f00 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
index e8b70f2..441af6e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
index 4e23c4e..65a74aa 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
index ced9175..addfcf2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
index 92d4a19..b87ce50 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
index a208736..9b8e776 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
index f407bc9..6a3c498 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
index 5bf6aca..07c9218 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
index b8a65c2..c612b94 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
index a978b68..7c66e93 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
index 710dd52..c76490a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
index a7b35e4..a2fff6f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
index bb05449..1259050 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
index a144222..bd08b97 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
index b0eafb6..0c3c0ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
index f6b83d0..40e6f7e3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
index c9da7b9..81c0c10 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
index bb41db0..6ac52f9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
index 7f6fa9c..f8c4b81 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
index 7f6fa9c..f8c4b81 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
index ca20839..d5a768c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
index 1ad5d8b..a697fa6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
index 6eba560..018c951 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
index f2358dd..95b5d3d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
index 1ebe23e..922790e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
index 468ad7d..df74fc3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
index d9f2a0d..2a527c9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
index 290822a..bf88418 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
index e0a3141..8e04b25 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
index 116b8e2..44bd99f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
old mode 100755
new mode 100644
index 827d84a..876d9ee
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
old mode 100755
new mode 100644
index d62502d..436f16d
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
old mode 100755
new mode 100644
index edc6023..876d9ee
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
index 3aa22f5..d52cb1a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
index 9216030..0cfdca0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
index 1afd107..4b805c4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
index 0de5760..7bbfbd1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
index 3af5991..ef8ac73 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
index e042696..60b75ef 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
index 25ca124..632127a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
index 49b0175..0b48667 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
index 88b08c8..0fba69d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
index 496df52..b0182a0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
index 940adf0..da8a957 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
index fab2e10..db75f745 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
index 3f4dedd..e19bf64 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
index ff474b6..9e22573 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
index 83045ce..8387514 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
index 2725ed2..a0c3bc7 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
index 409bb31..504990e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
index f5c0aa3..35f7741 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
index 38c7f07..d35736e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
index 429e818..a8820e9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
index ade3716..3416151 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
index 83cb820..435d25d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
index 174d65c..0e1964c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
index 9c3c44c..68f4530 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
index 08b975a..584e703 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
index 5799ad2..b114fea 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
index ec617d7..de3f56f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
index 5d9957a..b65df27 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
index 1260c59..7f7074e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
index ae9dc40..2b4af59 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
index ed157a8..fb70ba87 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
index 0ec4c64..ca3d5bf 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
index 60dc8a6..a17e1d7 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
index fe2ba7a..b5ab8b3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
index 150a6c7..8e9c451 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
index 76f86dc..25e9394 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
index 42a798a..0478d70 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
index 1f0dd89..6de73be 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
index 1643e6e..e78a0b1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
index 5e7ae35..02d4b3f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
index 06ae2ca..24c75ec 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
index b861bc9..108c054 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
index 8f1831d..7027dc4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
index 8f16376..a9d22d6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
index 12138d3..b0e83dc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
index 67f46d3..0ed3c8f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
index 11fd5e9..01945ff 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
index 165348c..dc36e0e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
index 8bbc5ba..725a507 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
index d53d3bc..f3fd89a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
index c817598..193af25 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
new file mode 100644
index 0000000..22215ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
index ce64926..1fd5dd3 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
index c63c426..b2edd46 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png b/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
index 85394fa..0eb71d0 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
index 3b7c9c7..90b4baf 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
index 653acbb..bc7034a 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
index 6c588f7..6f19bf4 100644
--- a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
index 13b18d8..9de8324 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
index dbcefee..75a020c 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png b/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
index 6e13ebe..4d5135e 100644
--- a/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png b/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
old mode 100755
new mode 100644
index 7d17a54..269049e
--- a/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
index d960c78..e7828c9 100644
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
old mode 100755
new mode 100644
index 3e46370..0e8c25c
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
old mode 100755
new mode 100644
index afc91b9..536357a
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png b/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
old mode 100755
new mode 100644
index 7086def..1ea924f
--- a/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
new file mode 100644
index 0000000..275e492
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
new file mode 100644
index 0000000..03f4732
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
new file mode 100644
index 0000000..7bfdb46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
new file mode 100644
index 0000000..4e20851
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
new file mode 100644
index 0000000..1c1b26b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..ed968c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
new file mode 100644
index 0000000..31ac35d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..5641b2b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..1ea83fc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4cb305d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..85df060
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png
new file mode 100644
index 0000000..0019a32
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..dc08550
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
new file mode 100644
index 0000000..bc024da
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..03885fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png
new file mode 100644
index 0000000..92e86c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..2e6e3ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..31d35c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..334213b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..dd98b0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..94acf9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
new file mode 100644
index 0000000..155c788
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
new file mode 100644
index 0000000..e84f3fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
new file mode 100644
index 0000000..7c21c48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..1fe6b91
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..4fc936b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..27357ea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 0000000..bbf5f7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..f0cc341d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..7e8504c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..53c7094
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..a882b94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
new file mode 100644
index 0000000..b375396
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..fdcf409
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png
new file mode 100644
index 0000000..792bac4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..31b4663
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png
new file mode 100644
index 0000000..45b5bf3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
new file mode 100644
index 0000000..54e3d1e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..bcea4f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..d915a9d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..6cf2053
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..d4a2068
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..4be3873
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..31e4813
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..032fa29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..52ad541
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..d7248b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..5d1a99c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..b342507
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..b618f75
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..11946cd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..e227309
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..4b0838c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..ecd4396e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..8c5465a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..9e7992a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..ccf5b0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..04918c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..34da296
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..f6cb0ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..eb4927a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..14087e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..87b67b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..33fa2ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..a84382f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..b59a72e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..c7927d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..eddb4eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..2759a8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..f129965a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..1abe164
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..06dc700
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..d1ae45d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..0c93241
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..3be20a2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..502382e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..b423454
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..b084871
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..8cbaff3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..0e53656
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..55c66b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..103927b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..2a0c21a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..23dfd7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..1258359
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..32c1432
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..b56be83
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..cd37477
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png
new file mode 100644
index 0000000..347b219
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png
new file mode 100644
index 0000000..ef5b653
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png
new file mode 100644
index 0000000..cd96a4a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png
new file mode 100644
index 0000000..02461a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png
new file mode 100644
index 0000000..033267f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png
new file mode 100644
index 0000000..73ae175
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png
new file mode 100644
index 0000000..1355da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png
new file mode 100644
index 0000000..ceb316c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png
new file mode 100644
index 0000000..ff4a0b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png
new file mode 100644
index 0000000..b2ebf40
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png
new file mode 100644
index 0000000..7f833ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png
new file mode 100644
index 0000000..b47e4c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png
new file mode 100644
index 0000000..4f88492
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png
new file mode 100644
index 0000000..7f7e1ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png
new file mode 100644
index 0000000..f0ab081
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png
new file mode 100644
index 0000000..e556da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png
new file mode 100644
index 0000000..a28d771
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png
new file mode 100644
index 0000000..7be9754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png
new file mode 100644
index 0000000..16271a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
new file mode 100644
index 0000000..263c591
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png
new file mode 100644
index 0000000..edff8db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png
new file mode 100644
index 0000000..e7938f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png
new file mode 100644
index 0000000..e7938f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png
new file mode 100644
index 0000000..33fda46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png
new file mode 100644
index 0000000..1d5484b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png
new file mode 100644
index 0000000..478b293
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png
new file mode 100644
index 0000000..b9cff0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png
new file mode 100644
index 0000000..4945e23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png
new file mode 100644
index 0000000..a55ecd8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png
new file mode 100644
index 0000000..0641c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png
new file mode 100644
index 0000000..d0eebb6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
new file mode 100644
index 0000000..cd89105
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..e85d643
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png
new file mode 100644
index 0000000..51b291c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
new file mode 100644
index 0000000..23d30fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
new file mode 100644
index 0000000..51b291c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..726f7ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..ec4f934
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..a77c8a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
new file mode 100644
index 0000000..fb98eef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..1527803
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
new file mode 100644
index 0000000..b86d47a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png
new file mode 100644
index 0000000..e487f5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..64ddafd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
new file mode 100644
index 0000000..7269f96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..6cf7a28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
new file mode 100644
index 0000000..f57e62d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..0bc3d0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
new file mode 100644
index 0000000..3d513fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..34ec231
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
new file mode 100644
index 0000000..32556f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png
new file mode 100644
index 0000000..15d0f2f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..c7c1e3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
new file mode 100644
index 0000000..afac648
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..6e4dc8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
new file mode 100644
index 0000000..60c0e7f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..90ca4e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png
new file mode 100644
index 0000000..befa1eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..419afa0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png
new file mode 100644
index 0000000..93af4fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png
new file mode 100644
index 0000000..c3f9e5d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..b20c61b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..b51178d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..0df470a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..485d407
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png
new file mode 100644
index 0000000..19cf3b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png
new file mode 100644
index 0000000..d28972f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..6ed28c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..4f462ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..66d8f80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..b2b2ace
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..5212337
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
new file mode 100644
index 0000000..d8d5e8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..43e590b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
new file mode 100644
index 0000000..2b0b54f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..e900d6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
new file mode 100644
index 0000000..85c65b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..990734c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
new file mode 100644
index 0000000..a7e9aaf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..d982c1f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
new file mode 100644
index 0000000..21aba7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..daf2750
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
new file mode 100644
index 0000000..41db8dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..b93e9ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
new file mode 100644
index 0000000..ae95d26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..576f120
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
new file mode 100644
index 0000000..4ad2c5c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png
new file mode 100644
index 0000000..52354bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..ce01276
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..1848fcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..846bc49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..a983e12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..7c6e44e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..a08c5f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6aa38bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..36c26b6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..55940d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..f65ef5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..8a0f4e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..2d81b22
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..4c08cff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..27d3b50
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..f017dd1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..6cd2c71
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..76195ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..fb097b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..04740b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..147d256
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..de808a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..d19d6ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..4bce24d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..0467e12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..0809456
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..0e8ec073
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..f9d2737
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..f5b2c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..eb1b18a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..1abe28a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..e896cbb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..b44123c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..d0cc5794e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..903b03e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..9578a218
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..c5e5cda
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..0730e3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..eafed59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..ea66c75
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..11ee533
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..43edb8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..7919030
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..0699681
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..9504838
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..db8bedb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..89e1b2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..88f720d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..89fcbd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..0ec439c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..4b22619
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..9b8c889
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..e601a90
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..b65c93f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..80fdafe1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..c54f630e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..8cfc59b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..3381016
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..0a77e7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..660b3a0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..0c278ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..921d88b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..4c6c08e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..de32ddd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png
new file mode 100644
index 0000000..001811f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..3d0fbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4362836
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..f4ccd7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..6392fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..f6ee596
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..5087adb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..4c212e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..bf23074
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..45dcf77
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..a2848de
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..89c998b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..9269d6e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..344ae30
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..13b5cae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..6647559
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..a0e67c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..9a75c24
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..a1f73c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..6b17f1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..9553580
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..8507f39
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..6966cec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..84ce77f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..b8670f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..a885aab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..32f08c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..0111893
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..a9c547e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..6801953
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..3ae2537
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..8a9f2e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..8c5c482
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..36c2cf8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..aee1eed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..30884a96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..ce91aa9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..82a4f61
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..55b6b38
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..519154d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..cdbab37
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..ec398cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..b1f16d6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..e15a12b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..90a1a3d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..21d944a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..9b2263f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..ca36237
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..2cea010
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..3d22838
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..3bee795
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..ad6bdce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..6d68d4e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..04ddb65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..830b006
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..f3be79b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..7f33567
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..471a900
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..b153c83
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..3a5ddb7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..609117c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..d8cd1fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..806b43b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..f699434
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..64d8b5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..4e718b07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..7306b48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..f414632
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..9e7a84a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..e17ce98
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..861b0b7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..fe1330b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..d459a00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..debd23e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..69ba222
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..7d862bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..6687c82
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..8438e76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..1842da2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..f9d2754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..892ba42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..73e0886
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..dc3aae3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..9d0fe7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..d3f6f55
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..7170a84
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..febf9588
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..4da4f54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..e775572
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..5e0617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..da2926f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..fef89cf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..c543b9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..3395fff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..612843d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..9de3703
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..dabfec5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..0ca6fbf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..aa73096
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..b534296
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..a33c488
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..fdd9c92
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..5454b49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..e338fd96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..549b7d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..9779320
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..5ca5827
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..174ef2d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..3e9dece
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..8952833
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..180a13b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..b9efa16
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..d8493ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..885831e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..03fcf54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..9bf7bec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..15a82ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..eb9ce59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..1c62fe3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..09cdfc4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..5447a85
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..04187de
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index b97c6a5..51e7d97 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -25,106 +25,145 @@
     android:layout_width="match_parent"
     >
 
-    <FrameLayout
-        android:id="@+id/background"
+    <FrameLayout android:id="@+id/rot0"
         android:layout_height="match_parent"
         android:layout_width="match_parent"
         android:background="#FF000000"
         >
 
-        <LinearLayout android:id="@+id/rot0"
+        <LinearLayout
             android:layout_height="match_parent"
             android:layout_width="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
             android:orientation="horizontal"
             >
 
             <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="wrap_content"
+            <View
+                android:layout_width="40dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_back"
+                android:layout_weight="0"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_width="80dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_back_default"
                 systemui:keyCode="4"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="wrap_content"
+                android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_home"
+                android:src="@drawable/ic_sysbar_home_default"
                 systemui:keyCode="3"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="wrap_content"
+            <ImageView android:id="@+id/recent_apps"
+                android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_menu"
+                android:src="@drawable/ic_sysbar_recent_default"
+                android:layout_weight="0"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_width="40dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_menu_default"
                 systemui:keyCode="82"
-                android:layout_weight="1"
+                android:layout_weight="0"
+                android:visibility="invisible"
                 />
         </LinearLayout>
 
-        <LinearLayout android:id="@+id/rot90"
-            android:layout_height="match_parent"
+        <View android:id="@+id/deadzone"
+            android:layout_height="@dimen/navigation_bar_deadzone_size"
             android:layout_width="match_parent"
-            android:orientation="vertical"
-            android:visibility="gone"
-            >
-
-            <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_home"
-                systemui:keyCode="3"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_back"
-                systemui:keyCode="4"
-                android:layout_weight="1"
-                />
-        </LinearLayout>
-
-        <LinearLayout android:id="@+id/rot270"
-            android:layout_height="match_parent"
-            android:layout_width="match_parent"
-            android:orientation="vertical"
-            android:visibility="gone"
-            >
-
-            <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_back"
-                systemui:keyCode="4"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_home"
-                systemui:keyCode="3"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="1"
-                />
-        </LinearLayout>
-    
+            android:layout_gravity="top"
+            android:clickable="true"
+            />
     </FrameLayout>
+
+    <FrameLayout android:id="@+id/rot90"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:background="#FF000000"
+        android:visibility="gone"
+        android:paddingTop="24dp"
+        >
+
+        <LinearLayout 
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            >
+            
+            <!-- navigation controls -->
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_menu_default_land"
+                systemui:keyCode="82"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
+            <ImageView android:id="@+id/recent_apps"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_recent_default_land"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_home_default_land"
+                systemui:keyCode="3"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_back_default_land"
+                systemui:keyCode="4"
+                android:layout_weight="0"
+                />
+            <View
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:layout_weight="0"
+                />
+        </LinearLayout>
+
+        <View android:id="@+id/deadzone"
+            android:layout_width="@dimen/navigation_bar_deadzone_size"
+            android:layout_height="match_parent"
+            android:layout_gravity="left"
+            android:clickable="true"
+            />
+    </FrameLayout>
+
+    <!-- not used -->
+    <View android:id="@+id/rot270"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="gone"
+        />
+
 </com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fc35a48..da28e1e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -40,7 +40,11 @@
     <dimen name="peek_window_y_offset">-12dp</dimen>
 
     <!-- thickness (height) of the navigation bar on phones that require it -->
-    <dimen name="navigation_bar_size">42dp</dimen>
+    <dimen name="navigation_bar_size">48dp</dimen>
+
+    <!-- thickness (height) of the dead zone at the top of the navigation bar,
+         reducing false presses on navbar buttons; approx 2mm -->
+    <dimen name="navigation_bar_deadzone_size">12dp</dimen>
 
     <!-- thickness (height) of each notification row, including any separators or padding -->
     <dimen name="notification_height">65dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 7dafb892..550fc57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -36,14 +36,24 @@
 import com.android.systemui.R;
 
 public class NavigationBarView extends LinearLayout {
+    final static boolean DEBUG_DEADZONE = false;
+
     final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
 
     protected IStatusBarService mBarService;
     final Display mDisplay;
+    View mCurrentView = null;
     View[] mRotatedViews = new View[4];
-    View mBackground;
     Animator mLastAnimator = null;
 
+    public View getRecentsButton() {
+        return mCurrentView.findViewById(R.id.recent_apps);
+    }
+
+    public View getMenuButton() {
+        return mCurrentView.findViewById(R.id.menu);
+    }
+
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mDisplay = ((WindowManager)context.getSystemService(
@@ -65,13 +75,13 @@
     }
 
     private void setLights(final boolean on) {
-        float oldAlpha = mBackground.getAlpha();
+        float oldAlpha = mCurrentView.getAlpha();
         android.util.Log.d("NavigationBarView", "animating alpha: " + oldAlpha + " -> "
             + (on ? 1f : 0f));
 
         if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
 
-        mLastAnimator = ObjectAnimator.ofFloat(mBackground, "alpha", oldAlpha, on ? 1f : 0f)
+        mLastAnimator = ObjectAnimator.ofFloat(mCurrentView, "alpha", oldAlpha, on ? 1f : 0f)
             .setDuration(on ? 250 : 1500);
         mLastAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -83,8 +93,6 @@
     }
 
     public void onFinishInflate() {
-        mBackground = findViewById(R.id.background);
-
         mRotatedViews[Surface.ROTATION_0] = 
         mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
 
@@ -93,6 +101,8 @@
         mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
                                                 ? findViewById(R.id.rot90)
                                                 : findViewById(R.id.rot270);
+
+        mCurrentView = mRotatedViews[Surface.ROTATION_0];
     }
 
     @Override
@@ -107,7 +117,12 @@
         for (int i=0; i<4; i++) {
             mRotatedViews[i].setVisibility(View.GONE);
         }
-        mRotatedViews[rot].setVisibility(View.VISIBLE);
+        mCurrentView = mRotatedViews[rot];
+        mCurrentView.setVisibility(View.VISIBLE);
+
+        if (DEBUG_DEADZONE) {
+            mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
+        }
 
         android.util.Log.d("NavigationBarView", "reorient(): rot=" + mDisplay.getRotation());
     }
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 f3c2623..d8474db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -372,11 +372,20 @@
         return res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
     }
 
+    private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            toggleRecentApps();
+        }
+    };
+
     // For small-screen devices (read: phones) that lack hardware navigation buttons
     private void addNavigationBar() {
         if (mNavigationBarView == null) return;
         
         mNavigationBarView.reorient();
+ 
+        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+
         WindowManagerImpl.getDefault().addView(
                 mNavigationBarView, getNavigationBarLayoutParams());
     }
@@ -385,6 +394,9 @@
         if (mNavigationBarView == null) return;
         
         mNavigationBarView.reorient();
+
+        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+
         WindowManagerImpl.getDefault().updateViewLayout(
                 mNavigationBarView, getNavigationBarLayoutParams());
     }
@@ -1230,8 +1242,20 @@
         }
     }
 
+    public void topAppWindowChanged(boolean showMenu) {
+        if (DEBUG) {
+            Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
+        }
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getMenuButton().setVisibility(showMenu
+                ? View.VISIBLE : View.INVISIBLE);
+        }
+
+        // See above re: lights-out policy for legacy apps.
+        if (showMenu) setLightsOn(true);
+    }
+
     // Not supported
-    public void topAppWindowChanged(boolean visible) { }
     public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { }
     @Override
     public void setHardKeyboardStatus(boolean available, boolean enabled) { }
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 93f7af3..df09f84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -1001,14 +1001,14 @@
         mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
     }
 
-    public void topAppWindowChanged(boolean windowVisible) {
+    public void topAppWindowChanged(boolean showMenu) {
         if (DEBUG) {
-            Slog.d(TAG, (windowVisible?"showing":"hiding") + " the MENU button");
+            Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
         }
-        mMenuButton.setVisibility(windowVisible ? View.VISIBLE : View.GONE);
+        mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
 
         // See above re: lights-out policy for legacy apps.
-        if (windowVisible) setLightsOn(true);
+        if (showMenu) setLightsOn(true);
 
         mCompatModeButton.refresh();
         if (mCompatModeButton.getVisibility() == View.VISIBLE) {
@@ -1040,7 +1040,7 @@
             }
         });
 
-        WindowManager.LayoutParams lp = mNotificationPanelParams = new WindowManager.LayoutParams(
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
index 187a486..60906a1 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
@@ -1,93 +1,96 @@
-/*

- * Copyright (C) 2011 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package com.android.systemui.usb;

-

-import android.app.Activity;

-import android.app.AlertDialog;

-import android.content.Context;

-import android.content.DialogInterface;

-import android.hardware.usb.UsbManager;

-import android.os.Bundle;

-import android.view.LayoutInflater;

-import android.view.View;

-import android.util.Log;

-import android.widget.Button;

-

-import java.io.File;

-

-import com.android.systemui.R;

-

-public class UsbPreferenceActivity extends Activity implements View.OnClickListener  {

-

-    private static final String TAG = "UsbPreferenceActivity";

-

-    private UsbManager mUsbManager;

-    private String mCurrentFunction;

-    private String[] mFunctions;

-    private String mInstallerImagePath;

-    private Button mMtpPtpButton;

-    private Button mInstallerCdButton;

-    private boolean mPtpActive;

-

-    @Override

-    public void onCreate(Bundle icicle) {

-        super.onCreate(icicle);

-

-        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);

-

-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);

-        dialogBuilder.setTitle(getString(R.string.usb_preference_title));

-

-        LayoutInflater inflater = (LayoutInflater)getSystemService(

-                Context.LAYOUT_INFLATER_SERVICE);

-        View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);

-        dialogBuilder.setView(buttonView);

-        mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);

-        mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);

-        mMtpPtpButton.setOnClickListener(this);

-        mInstallerCdButton.setOnClickListener(this);

-

-        mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);

-        if (mPtpActive) {

-            mMtpPtpButton.setText(R.string.use_mtp_button_title);

-        }

-

-        mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);

-        if (!(new File(mInstallerImagePath)).exists()) {

-            mInstallerCdButton.setVisibility(View.GONE);

-        }

-

-        dialogBuilder.show();

-    }

-

-    public void onClick(View v) {

-        if (v.equals(mMtpPtpButton)) {

-            if (mPtpActive) {

-                mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_MTP);

-                mUsbManager.setDefaultFunction(UsbManager.USB_FUNCTION_MTP);

-            } else {

-                mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_PTP);

-                mUsbManager.setDefaultFunction(UsbManager.USB_FUNCTION_PTP);

-            }

-        } else if (v.equals(mInstallerCdButton)) {

-            mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_MASS_STORAGE);

-            mUsbManager.setMassStorageBackingFile(mInstallerImagePath);

-        }

-

+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.util.Log;
+import android.widget.Button;
+
+import java.io.File;
+
+import com.android.systemui.R;
+
+public class UsbPreferenceActivity extends Activity implements View.OnClickListener  {
+
+    private static final String TAG = "UsbPreferenceActivity";
+
+    private UsbManager mUsbManager;
+    private String mCurrentFunction;
+    private String[] mFunctions;
+    private String mInstallerImagePath;
+    private AlertDialog mDialog;
+    private Button mMtpPtpButton;
+    private Button mInstallerCdButton;
+    private boolean mPtpActive;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
+
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+        dialogBuilder.setTitle(getString(R.string.usb_preference_title));
+
+        LayoutInflater inflater = (LayoutInflater)getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);
+        dialogBuilder.setView(buttonView);
+        mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);
+        mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);
+        mMtpPtpButton.setOnClickListener(this);
+        mInstallerCdButton.setOnClickListener(this);
+
+        mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);
+        if (mPtpActive) {
+            mMtpPtpButton.setText(R.string.use_mtp_button_title);
+        }
+
+        mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);
+        if (!(new File(mInstallerImagePath)).exists()) {
+            mInstallerCdButton.setVisibility(View.GONE);
+        }
+
+        mDialog = dialogBuilder.show();
+    }
+
+    public void onClick(View v) {
+        if (v.equals(mMtpPtpButton)) {
+            if (mPtpActive) {
+                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
+            } else {
+                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
+            }
+        } else if (v.equals(mInstallerCdButton)) {
+            // installer CD is never default
+            mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, false);
+            mUsbManager.setMassStorageBackingFile(mInstallerImagePath);
+        }
+
+        if (mDialog != null) {
+            mDialog.dismiss();
+        }
         finish();

-    }

-}

+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
index c4feefd..de4ea75 100644
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -110,7 +110,7 @@
         mOk = (Button) findViewById(R.id.ok);
         mOk.setOnClickListener(this);
 
-        mEmergencyCall = (Button) findViewById(R.id.emergencyCall);
+        mEmergencyCall = (Button) findViewById(R.id.emergencyCallButton);
         mEmergencyCall.setOnClickListener(this);
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
 
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index eea30407..b60bae7 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -682,8 +682,9 @@
             final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
                     == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 
-            boolean showSlidingTab = getResources().getBoolean(R.bool.config_enableSlidingTabFirst);
-            if (isSecure() && (usingLockPattern || !showSlidingTab)) {
+            boolean showLockBeforeUnlock = getResources()
+                    .getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+            if (isSecure() && (usingLockPattern || !showLockBeforeUnlock)) {
                 return Mode.UnlockScreen;
             } else {
                 return Mode.LockScreen;
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 6734005..f862d01 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -129,7 +129,7 @@
                     | InputType.TYPE_TEXT_VARIATION_PASSWORD);
         }
 
-        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         mEmergencyCallButton.setOnClickListener(this);
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
 
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index cd79b60..6573286 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -183,8 +183,7 @@
 
         mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
         // This shows up when no other information is required on status1
-        mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,
-                StatusView.LOCK_ICON);
+        //mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,StatusView.LOCK_ICON);
 
         mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 75f466a..7f6327d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -498,6 +498,7 @@
             return;
         }
 
+        int width = WRAP_CONTENT;
         if (st.decorView == null || st.refreshDecorView) {
             if (st.decorView == null) {
                 // Initialize the panel decor, this will populate st.decorView
@@ -523,6 +524,7 @@
                 // If the contents is fill parent for the width, set the
                 // corresponding background
                 backgroundResId = st.fullBackground;
+                width = MATCH_PARENT;
             } else {
                 // Otherwise, set the normal panel background
                 backgroundResId = st.background;
@@ -546,7 +548,7 @@
         st.isHandled = false;
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                WRAP_CONTENT, WRAP_CONTENT,
+                width, WRAP_CONTENT,
                 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
                 WindowManager.LayoutParams.FLAG_DITHER
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
@@ -709,9 +711,7 @@
                     mActionBar.isOverflowReserved()) {
                 if (mActionBar.getVisibility() == View.VISIBLE) {
                     if (!mActionBar.isOverflowMenuShowing()) {
-                        final Callback cb = getCallback();
-                        if (cb != null && !isDestroyed() &&
-                                cb.onPreparePanel(featureId, st.createdPanelView, st.menu)) {
+                        if (!isDestroyed() && preparePanel(st, event)) {
                             playSoundEffect = mActionBar.showOverflowMenu();
                         }
                     } else {
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
index 544bb3d..7e8d547 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -109,7 +109,7 @@
         mDelPinButton.setOnClickListener(this);
 
 
-        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         mOkButton = (TextView) findViewById(R.id.ok);
 
         mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 7255c27..ec917f0 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -99,7 +99,7 @@
 
         mOkButton.setOnClickListener(this);
 
-        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         mEmergencyCallButton.setOnClickListener(this);
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
 
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 46ce5a3..79f81ff 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -40,7 +40,7 @@
 
     private String mInstructions = null;
     private TextView mStatus1;
-    private TextView mPropertyOf;
+    private TextView mOwnerInfo;
 
     private boolean mHasCarrier;
     private boolean mHasDate;
@@ -105,7 +105,7 @@
         mStatus1 = (TextView) findViewById(R.id.status1);
         mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
         mAlarmStatus.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
-        mPropertyOf = (TextView) findViewById(R.id.propertyOf);
+        mOwnerInfo = (TextView) findViewById(R.id.propertyOf);
 
         resetStatusInfo(updateMonitor, lockPatternUtils);
 
@@ -153,20 +153,22 @@
     void updateStatusLines(boolean showStatusLines) {
         if (!showStatusLines) {
             mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
-            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
+            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
             return;
         }
 
         // Update owner info
-        if (mPropertyOf != null) {
-            ContentResolver res = getContext().getContentResolver();
-            String info = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
-            boolean enabled = Settings.Secure.getInt(res,
-                    Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
-
-            mPropertyOf.setText(info);
-            mPropertyOf.setVisibility(enabled && !TextUtils.isEmpty(info) ?
-                    View.VISIBLE : View.INVISIBLE);
+        final ContentResolver res = getContext().getContentResolver();
+        final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
+                Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
+        String ownerInfo = null;
+        if (ownerInfoEnabled) {
+            ownerInfo = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
+            if (mOwnerInfo != null) {
+                mOwnerInfo.setText(ownerInfo);
+                mOwnerInfo.setVisibility(ownerInfoEnabled && !TextUtils.isEmpty(ownerInfo) ?
+                        View.VISIBLE : View.INVISIBLE);
+            }
         }
 
         // Update Alarm status
@@ -175,7 +177,7 @@
             mAlarmStatus.setText(nextAlarm);
             mAlarmStatus.setVisibility(View.VISIBLE);
         } else {
-            mAlarmStatus.setVisibility(View.INVISIBLE);
+            mAlarmStatus.setVisibility(View.GONE);
         }
 
         // Update Status1
@@ -204,15 +206,16 @@
             } else {
                 mStatus1.setVisibility(View.INVISIBLE);
             }
+        } else if (mHelpMessageId != 0) {
+            mStatus1.setText(mHelpMessageId);
+            mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
+            mStatus1.setVisibility(View.VISIBLE);
+        } else if (ownerInfoEnabled && mOwnerInfo == null && ownerInfo != null) {
+            mStatus1.setText(ownerInfo);
+            mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0,0, 0);
+            mStatus1.setVisibility(View.VISIBLE);
         } else {
-            // nothing specific to show; show help message and icon, if provided
-            if (mHelpMessageId != 0) {
-                mStatus1.setText(mHelpMessageId);
-                mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
-                mStatus1.setVisibility(View.VISIBLE);
-            } else {
-                mStatus1.setVisibility(View.INVISIBLE);
-            }
+            mStatus1.setVisibility(View.INVISIBLE);
         }
     }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 44df5b5..f716e63 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2936,7 +2936,7 @@
         mStreamType = streamType;
         // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
         // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
-        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(int8_t);
+        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
     }
 }
 
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a3749cf..a583aad 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -559,13 +559,8 @@
         ANativeWindowBuffer* anb;
         rc = a->dequeueBuffer(a, &anb);
         if (!rc) {
-            rc = a->lockBuffer(a, anb);
-            if (!rc) {
-                *buffer = &anb->handle;
-                *stride = anb->stride;
-            }
-            else
-                a->cancelBuffer(a, anb);
+            *buffer = &anb->handle;
+            *stride = anb->stride;
         }
         return rc;
     }
@@ -576,6 +571,14 @@
         (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
 #endif
 
+    static int __lock_buffer(struct preview_stream_ops* w,
+                      buffer_handle_t* buffer)
+    {
+        ANativeWindow *a = anw(w);
+        return a->lockBuffer(a,
+                  container_of(buffer, ANativeWindowBuffer, handle));
+    }
+
     static int __enqueue_buffer(struct preview_stream_ops* w,
                       buffer_handle_t* buffer)
     {
@@ -641,6 +644,7 @@
     void initHalPreviewWindow()
     {
         mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
+        mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
         mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
         mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
         mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a011ae2..9b09983 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -420,6 +420,10 @@
     // allow anyone to use camera (after they lock the camera)
     status_t result = checkPid();
     if (result == NO_ERROR) {
+        if (mHardware->recordingEnabled()) {
+            LOGE("Not allowed to unlock camera during recording.");
+            return INVALID_OPERATION;
+        }
         mClientPid = 0;
         LOG1("clear mCameraClient (pid %d)", callingPid);
         // we need to remove the reference to ICameraClient so that when the app
@@ -756,6 +760,11 @@
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
 
+    if (mHardware->recordingEnabled()) {
+        LOGE("Cannot take picture during recording.");
+        return INVALID_OPERATION;
+    }
+
     if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
         (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
         LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 4a50d8a..85ce38a 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -569,9 +569,9 @@
         break;
     case DROP_REASON_BLOCKED:
         LOGI("Dropped event because the current application is not responding and the user "
-                "has started interating with a different application.");
+                "has started interacting with a different application.");
         reason = "inbound event was dropped because the current application is not responding "
-                "and the user has started interating with a different application";
+                "and the user has started interacting with a different application";
         break;
     case DROP_REASON_STALE:
         LOGI("Dropped event because it is stale.");
@@ -1239,37 +1239,35 @@
     const InputWindow* newHoverWindow = NULL;
 
     bool isSplit = mTouchState.split;
-    bool wrongDevice = mTouchState.down
-            && (mTouchState.deviceId != entry->deviceId
-                    || mTouchState.source != entry->source);
+    bool switchedDevice = mTouchState.deviceId != entry->deviceId
+            || mTouchState.source != entry->source;
     bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
             || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
             || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
     bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
             || maskedAction == AMOTION_EVENT_ACTION_SCROLL
             || isHoverAction);
+    bool wrongDevice = false;
     if (newGesture) {
         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        if (wrongDevice && !down) {
+        if (switchedDevice && mTouchState.down && !down) {
+#if DEBUG_FOCUS
+            LOGD("Dropping event because a pointer for a different device is already down.");
+#endif
             mTempTouchState.copyFrom(mTouchState);
-        } else {
-            mTempTouchState.reset();
-            mTempTouchState.down = down;
-            mTempTouchState.deviceId = entry->deviceId;
-            mTempTouchState.source = entry->source;
-            isSplit = false;
-            wrongDevice = false;
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            switchedDevice = false;
+            wrongDevice = true;
+            goto Failed;
         }
+        mTempTouchState.reset();
+        mTempTouchState.down = down;
+        mTempTouchState.deviceId = entry->deviceId;
+        mTempTouchState.source = entry->source;
+        isSplit = false;
     } else {
         mTempTouchState.copyFrom(mTouchState);
     }
-    if (wrongDevice) {
-#if DEBUG_FOCUS
-        LOGD("Dropping event because a pointer for a different device is already down.");
-#endif
-        injectionResult = INPUT_EVENT_INJECTION_FAILED;
-        goto Failed;
-    }
 
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
         /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
@@ -1598,18 +1596,38 @@
     // Update final pieces of touch state if the injector had permission.
     if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
         if (!wrongDevice) {
-            if (maskedAction == AMOTION_EVENT_ACTION_UP
-                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL
-                    || isHoverAction) {
+            if (switchedDevice) {
+#if DEBUG_FOCUS
+                LOGD("Conflicting pointer actions: Switched to a different device.");
+#endif
+                *outConflictingPointerActions = true;
+            }
+
+            if (isHoverAction) {
+                // Started hovering, therefore no longer down.
+                if (mTouchState.down) {
+#if DEBUG_FOCUS
+                    LOGD("Conflicting pointer actions: Hover received while pointer was down.");
+#endif
+                    *outConflictingPointerActions = true;
+                }
+                mTouchState.reset();
+                if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+                        || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+                    mTouchState.deviceId = entry->deviceId;
+                    mTouchState.source = entry->source;
+                }
+            } else if (maskedAction == AMOTION_EVENT_ACTION_UP
+                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
                 // All pointers up or canceled.
                 mTouchState.reset();
             } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
                 // First pointer went down.
                 if (mTouchState.down) {
-                    *outConflictingPointerActions = true;
 #if DEBUG_FOCUS
-                    LOGD("Pointer down received while already down.");
+                    LOGD("Conflicting pointer actions: Down received while already down.");
 #endif
+                    *outConflictingPointerActions = true;
                 }
                 mTouchState.copyFrom(mTempTouchState);
             } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
@@ -1868,6 +1886,18 @@
                 return;
             }
 
+            // If the motion event was modified in flight, then we cannot stream the sample.
+            if ((motionEventDispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_MASK)
+                    != InputTarget::FLAG_DISPATCH_AS_IS) {
+#if DEBUG_BATCHING
+                LOGD("channel '%s' ~ Not streaming because the motion event was not "
+                        "being dispatched as-is.  "
+                        "(Waiting for next dispatch cycle to start.)",
+                        connection->getInputChannelName());
+#endif
+                return;
+            }
+
             // The dispatch entry is in progress and is still potentially open for streaming.
             // Try to stream the new motion sample.  This might fail if the consumer has already
             // consumed the motion event (or if the channel is broken).
@@ -1972,6 +2002,66 @@
         dispatchEntry->headMotionSample = appendedMotionSample;
     }
 
+    // Apply target flags and update the connection's input state.
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+        dispatchEntry->resolvedAction = keyEntry->action;
+        dispatchEntry->resolvedFlags = keyEntry->flags;
+
+        if (!connection->inputState.trackKey(keyEntry,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+            LOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
+                    connection->getInputChannelName());
+#endif
+            return; // skip the inconsistent event
+        }
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+        if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+        } else {
+            dispatchEntry->resolvedAction = motionEntry->action;
+        }
+        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+                && !connection->inputState.isHovering(
+                        motionEntry->deviceId, motionEntry->source)) {
+#if DEBUG_DISPATCH_CYCLE
+        LOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
+                connection->getInputChannelName());
+#endif
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        }
+
+        dispatchEntry->resolvedFlags = motionEntry->flags;
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+        }
+
+        if (!connection->inputState.trackMotion(motionEntry,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+            LOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
+                    connection->getInputChannelName());
+#endif
+            return; // skip the inconsistent event
+        }
+        break;
+    }
+    }
+
     // Enqueue the dispatch entry.
     connection->outboundQueue.enqueueAtTail(dispatchEntry);
 }
@@ -1999,16 +2089,11 @@
     case EventEntry::TYPE_KEY: {
         KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
 
-        // Apply target flags.
-        int32_t action = keyEntry->action;
-        int32_t flags = keyEntry->flags;
-
-        // Update the connection's input state.
-        connection->inputState.trackKey(keyEntry, action);
-
         // Publish the key event.
-        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
-                action, flags, keyEntry->keyCode, keyEntry->scanCode,
+        status = connection->inputPublisher.publishKeyEvent(
+                keyEntry->deviceId, keyEntry->source,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+                keyEntry->keyCode, keyEntry->scanCode,
                 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
                 keyEntry->eventTime);
 
@@ -2024,24 +2109,6 @@
     case EventEntry::TYPE_MOTION: {
         MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
 
-        // Apply target flags.
-        int32_t action = motionEntry->action;
-        int32_t flags = motionEntry->flags;
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
-            action = AMOTION_EVENT_ACTION_OUTSIDE;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
-            action = AMOTION_EVENT_ACTION_HOVER_EXIT;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
-            action = AMOTION_EVENT_ACTION_HOVER_ENTER;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
-            action = AMOTION_EVENT_ACTION_CANCEL;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
-            action = AMOTION_EVENT_ACTION_DOWN;
-        }
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
-            flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-        }
-
         // If headMotionSample is non-NULL, then it points to the first new sample that we
         // were unable to dispatch during the previous cycle so we resume dispatching from
         // that point in the list of motion samples.
@@ -2082,13 +2149,11 @@
             }
         }
 
-        // Update the connection's input state.
-        connection->inputState.trackMotion(motionEntry, action);
-
         // Publish the motion event and the first motion sample.
-        status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
-                motionEntry->source, action, flags, motionEntry->edgeFlags,
-                motionEntry->metaState, motionEntry->buttonState,
+        status = connection->inputPublisher.publishMotionEvent(
+                motionEntry->deviceId, motionEntry->source,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+                motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
                 xOffset, yOffset,
                 motionEntry->xPrecision, motionEntry->yPrecision,
                 motionEntry->downTime, firstMotionSample->eventTime,
@@ -2102,8 +2167,8 @@
             return;
         }
 
-        if (action == AMOTION_EVENT_ACTION_MOVE
-                || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_MOVE
+                || dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
             // Append additional motion samples.
             MotionSample* nextMotionSample = firstMotionSample->next;
             for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
@@ -2355,23 +2420,22 @@
                 break;
             }
 
-            int32_t xOffset, yOffset;
-            float scaleFactor;
+            InputTarget target;
             const InputWindow* window = getWindowLocked(connection->inputChannel);
             if (window) {
-                xOffset = -window->frameLeft;
-                yOffset = -window->frameTop;
-                scaleFactor = window->scaleFactor;
+                target.xOffset = -window->frameLeft;
+                target.yOffset = -window->frameTop;
+                target.scaleFactor = window->scaleFactor;
             } else {
-                xOffset = 0;
-                yOffset = 0;
-                scaleFactor = 1.0f;
+                target.xOffset = 0;
+                target.yOffset = 0;
+                target.scaleFactor = 1.0f;
             }
+            target.inputChannel = connection->inputChannel;
+            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
 
-            DispatchEntry* cancelationDispatchEntry =
-                    mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
-                    0, xOffset, yOffset, scaleFactor);
-            connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
+            enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
+                    &target, false, InputTarget::FLAG_DISPATCH_AS_IS);
 
             mAllocator.releaseEventEntry(cancelationEventEntry);
         }
@@ -3327,6 +3391,7 @@
     resetTargetsLocked();
 
     mTouchState.reset();
+    mLastHoverWindow = NULL;
 }
 
 void InputDispatcher::logDispatchStateLocked() {
@@ -4125,111 +4190,186 @@
     return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
 }
 
-void InputDispatcher::InputState::trackEvent(const EventEntry* entry, int32_t action) {
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        trackKey(static_cast<const KeyEntry*>(entry), action);
-        break;
+bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+        const MotionMemento& memento = mMotionMementos.itemAt(i);
+        if (memento.deviceId == deviceId
+                && memento.source == source
+                && memento.hovering) {
+            return true;
+        }
+    }
+    return false;
+}
 
-    case EventEntry::TYPE_MOTION:
-        trackMotion(static_cast<const MotionEntry*>(entry), action);
-        break;
+bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
+        int32_t action, int32_t flags) {
+    switch (action) {
+    case AKEY_EVENT_ACTION_UP: {
+        if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+            for (size_t i = 0; i < mFallbackKeys.size(); ) {
+                if (mFallbackKeys.valueAt(i) == entry->keyCode) {
+                    mFallbackKeys.removeItemsAt(i);
+                } else {
+                    i += 1;
+                }
+            }
+        }
+        ssize_t index = findKeyMemento(entry);
+        if (index >= 0) {
+            mKeyMementos.removeAt(index);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
+                "keyCode=%d, scanCode=%d",
+                entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
+#endif
+        return false;
+    }
+
+    case AKEY_EVENT_ACTION_DOWN: {
+        ssize_t index = findKeyMemento(entry);
+        if (index >= 0) {
+            mKeyMementos.removeAt(index);
+        }
+        addKeyMemento(entry, flags);
+        return true;
+    }
+
+    default:
+        return true;
     }
 }
 
-void InputDispatcher::InputState::trackKey(const KeyEntry* entry, int32_t action) {
-    if (action == AKEY_EVENT_ACTION_UP
-            && (entry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
-        for (size_t i = 0; i < mFallbackKeys.size(); ) {
-            if (mFallbackKeys.valueAt(i) == entry->keyCode) {
-                mFallbackKeys.removeItemsAt(i);
-            } else {
-                i += 1;
-            }
+bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
+        int32_t action, int32_t flags) {
+    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+    switch (actionMasked) {
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_CANCEL: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+            return true;
         }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
+                "actionMasked=%d",
+                entry->deviceId, entry->source, actionMasked);
+#endif
+        return false;
     }
 
+    case AMOTION_EVENT_ACTION_DOWN: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+        }
+        addMotionMemento(entry, flags, false /*hovering*/);
+        return true;
+    }
+
+    case AMOTION_EVENT_ACTION_POINTER_UP:
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+    case AMOTION_EVENT_ACTION_MOVE: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            MotionMemento& memento = mMotionMementos.editItemAt(index);
+            memento.setPointers(entry);
+            return true;
+        }
+        if (actionMasked == AMOTION_EVENT_ACTION_MOVE
+                && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
+                        | AINPUT_SOURCE_CLASS_NAVIGATION))) {
+            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent motion pointer up/down or move event: "
+                "deviceId=%d, source=%08x, actionMasked=%d",
+                entry->deviceId, entry->source, actionMasked);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_HOVER_EXIT: {
+        ssize_t index = findMotionMemento(entry, true /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
+                entry->deviceId, entry->source);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_HOVER_ENTER:
+    case AMOTION_EVENT_ACTION_HOVER_MOVE: {
+        ssize_t index = findMotionMemento(entry, true /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+        }
+        addMotionMemento(entry, flags, true /*hovering*/);
+        return true;
+    }
+
+    default:
+        return true;
+    }
+}
+
+ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
     for (size_t i = 0; i < mKeyMementos.size(); i++) {
-        KeyMemento& memento = mKeyMementos.editItemAt(i);
+        const KeyMemento& memento = mKeyMementos.itemAt(i);
         if (memento.deviceId == entry->deviceId
                 && memento.source == entry->source
                 && memento.keyCode == entry->keyCode
                 && memento.scanCode == entry->scanCode) {
-            switch (action) {
-            case AKEY_EVENT_ACTION_UP:
-                mKeyMementos.removeAt(i);
-                return;
-
-            case AKEY_EVENT_ACTION_DOWN:
-                mKeyMementos.removeAt(i);
-                goto Found;
-
-            default:
-                return;
-            }
+            return i;
         }
     }
-
-Found:
-    if (action == AKEY_EVENT_ACTION_DOWN) {
-        mKeyMementos.push();
-        KeyMemento& memento = mKeyMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.keyCode = entry->keyCode;
-        memento.scanCode = entry->scanCode;
-        memento.flags = entry->flags;
-        memento.downTime = entry->downTime;
-    }
+    return -1;
 }
 
-void InputDispatcher::InputState::trackMotion(const MotionEntry* entry, int32_t action) {
-    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
+        bool hovering) const {
     for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        MotionMemento& memento = mMotionMementos.editItemAt(i);
+        const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (memento.deviceId == entry->deviceId
-                && memento.source == entry->source) {
-            switch (actionMasked) {
-            case AMOTION_EVENT_ACTION_UP:
-            case AMOTION_EVENT_ACTION_CANCEL:
-            case AMOTION_EVENT_ACTION_HOVER_ENTER:
-            case AMOTION_EVENT_ACTION_HOVER_MOVE:
-            case AMOTION_EVENT_ACTION_HOVER_EXIT:
-                mMotionMementos.removeAt(i);
-                return;
-
-            case AMOTION_EVENT_ACTION_DOWN:
-                mMotionMementos.removeAt(i);
-                goto Found;
-
-            case AMOTION_EVENT_ACTION_POINTER_UP:
-            case AMOTION_EVENT_ACTION_POINTER_DOWN:
-            case AMOTION_EVENT_ACTION_MOVE:
-                memento.setPointers(entry);
-                return;
-
-            default:
-                return;
-            }
+                && memento.source == entry->source
+                && memento.hovering == hovering) {
+            return i;
         }
     }
+    return -1;
+}
 
-Found:
-    switch (actionMasked) {
-    case AMOTION_EVENT_ACTION_DOWN:
-    case AMOTION_EVENT_ACTION_HOVER_ENTER:
-    case AMOTION_EVENT_ACTION_HOVER_MOVE:
-    case AMOTION_EVENT_ACTION_HOVER_EXIT:
-        mMotionMementos.push();
-        MotionMemento& memento = mMotionMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.xPrecision = entry->xPrecision;
-        memento.yPrecision = entry->yPrecision;
-        memento.downTime = entry->downTime;
-        memento.setPointers(entry);
-        memento.hovering = actionMasked != AMOTION_EVENT_ACTION_DOWN;
-    }
+void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
+    mKeyMementos.push();
+    KeyMemento& memento = mKeyMementos.editTop();
+    memento.deviceId = entry->deviceId;
+    memento.source = entry->source;
+    memento.keyCode = entry->keyCode;
+    memento.scanCode = entry->scanCode;
+    memento.flags = flags;
+    memento.downTime = entry->downTime;
+}
+
+void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
+        int32_t flags, bool hovering) {
+    mMotionMementos.push();
+    MotionMemento& memento = mMotionMementos.editTop();
+    memento.deviceId = entry->deviceId;
+    memento.source = entry->source;
+    memento.flags = flags;
+    memento.xPrecision = entry->xPrecision;
+    memento.yPrecision = entry->yPrecision;
+    memento.downTime = entry->downTime;
+    memento.setPointers(entry);
+    memento.hovering = hovering;
 }
 
 void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
@@ -4243,20 +4383,17 @@
 void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
         Allocator* allocator, Vector<EventEntry*>& outEvents,
         const CancelationOptions& options) {
-    for (size_t i = 0; i < mKeyMementos.size(); ) {
+    for (size_t i = 0; i < mKeyMementos.size(); i++) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
         if (shouldCancelKey(memento, options)) {
             outEvents.push(allocator->obtainKeyEntry(currentTime,
                     memento.deviceId, memento.source, 0,
                     AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
                     memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
-            mKeyMementos.removeAt(i);
-        } else {
-            i += 1;
         }
     }
 
-    for (size_t i = 0; i < mMotionMementos.size(); ) {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (shouldCancelMotion(memento, options)) {
             outEvents.push(allocator->obtainMotionEntry(currentTime,
@@ -4264,12 +4401,9 @@
                     memento.hovering
                             ? AMOTION_EVENT_ACTION_HOVER_EXIT
                             : AMOTION_EVENT_ACTION_CANCEL,
-                    0, 0, 0, 0,
+                    memento.flags, 0, 0, 0,
                     memento.xPrecision, memento.yPrecision, memento.downTime,
                     memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
-            mMotionMementos.removeAt(i);
-        } else {
-            i += 1;
         }
     }
 }
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 676d162..bdd1922 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -522,6 +522,10 @@
         // True if dispatch has started.
         bool inProgress;
 
+        // Set to the resolved action and flags when the event is enqueued.
+        int32_t resolvedAction;
+        int32_t resolvedFlags;
+
         // For motion events:
         //   Pointer to the first motion sample to dispatch in this cycle.
         //   Usually NULL to indicate that the list of motion samples begins at
@@ -709,14 +713,19 @@
         // Returns true if there is no state to be canceled.
         bool isNeutral() const;
 
-        // Records tracking information for an event that has just been published.
-        void trackEvent(const EventEntry* entry, int32_t action);
+        // Returns true if the specified source is known to have received a hover enter
+        // motion event.
+        bool isHovering(int32_t deviceId, uint32_t source) const;
 
         // Records tracking information for a key event that has just been published.
-        void trackKey(const KeyEntry* entry, int32_t action);
+        // Returns true if the event should be delivered, false if it is inconsistent
+        // and should be skipped.
+        bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
 
         // Records tracking information for a motion event that has just been published.
-        void trackMotion(const MotionEntry* entry, int32_t action);
+        // Returns true if the event should be delivered, false if it is inconsistent
+        // and should be skipped.
+        bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
 
         // Synthesizes cancelation events for the current state and resets the tracked state.
         void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
@@ -756,6 +765,7 @@
         struct MotionMemento {
             int32_t deviceId;
             uint32_t source;
+            int32_t flags;
             float xPrecision;
             float yPrecision;
             nsecs_t downTime;
@@ -771,6 +781,12 @@
         Vector<MotionMemento> mMotionMementos;
         KeyedVector<int32_t, int32_t> mFallbackKeys;
 
+        ssize_t findKeyMemento(const KeyEntry* entry) const;
+        ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
+
+        void addKeyMemento(const KeyEntry* entry, int32_t flags);
+        void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
+
         static bool shouldCancelKey(const KeyMemento& memento,
                 const CancelationOptions& options);
         static bool shouldCancelMotion(const MotionMemento& memento,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 3e4c666..82c3af3 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -53,6 +53,7 @@
 #define INDENT2 "    "
 #define INDENT3 "      "
 #define INDENT4 "        "
+#define INDENT5 "          "
 
 namespace android {
 
@@ -154,14 +155,15 @@
     case BTN_LEFT:
         return AMOTION_EVENT_BUTTON_PRIMARY;
     case BTN_RIGHT:
+    case BTN_STYLUS:
         return AMOTION_EVENT_BUTTON_SECONDARY;
     case BTN_MIDDLE:
+    case BTN_STYLUS2:
         return AMOTION_EVENT_BUTTON_TERTIARY;
     case BTN_SIDE:
         return AMOTION_EVENT_BUTTON_BACK;
-    case BTN_EXTRA:
-        return AMOTION_EVENT_BUTTON_FORWARD;
     case BTN_FORWARD:
+    case BTN_EXTRA:
         return AMOTION_EVENT_BUTTON_FORWARD;
     case BTN_BACK:
         return AMOTION_EVENT_BUTTON_BACK;
@@ -176,8 +178,7 @@
 static bool isPointerDown(int32_t buttonState) {
     return buttonState &
             (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
-                    | AMOTION_EVENT_BUTTON_TERTIARY
-                    | AMOTION_EVENT_BUTTON_ERASER);
+                    | AMOTION_EVENT_BUTTON_TERTIARY);
 }
 
 static int32_t calculateEdgeFlagsUsingPointerBounds(
@@ -921,7 +922,7 @@
     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
 #if DEBUG_RAW_EVENTS
         LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
-                "keycode=0x%04x value=0x%04x flags=0x%08x",
+                "keycode=0x%04x value=0x%08x flags=0x%08x",
                 rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
                 rawEvent->value, rawEvent->flags);
 #endif
@@ -1921,8 +1922,17 @@
         dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mLocked.distanceScale);
 
         dump.appendFormat(INDENT3 "Last Touch:\n");
-        dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
         dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
+        dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
+        for (uint32_t i = 0; i < mLastTouch.pointerCount; i++) {
+            const PointerData& pointer = mLastTouch.pointers[i];
+            dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
+                    "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
+                    "orientation=%d, distance=%d, isStylus=%s\n", i,
+                    pointer.id, pointer.x, pointer.y, pointer.pressure,
+                    pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, pointer.toolMinor,
+                    pointer.orientation, pointer.distance, toString(pointer.isStylus));
+        }
 
         if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
             dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
@@ -3704,6 +3714,29 @@
                 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
                 mPointerGesture.currentGestureIdBits, -1,
                 0, 0, mPointerGesture.downTime);
+    } else if (dispatchedGestureIdBits.isEmpty()
+            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
+        // Synthesize a hover move event after all pointers go up to indicate that
+        // the pointer is hovering again even if the user is not currently touching
+        // the touch pad.  This ensures that a view will receive a fresh hover enter
+        // event after a tap.
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+
+        PointerProperties pointerProperties;
+        pointerProperties.clear();
+        pointerProperties.id = 0;
+        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+
+        PointerCoords pointerCoords;
+        pointerCoords.clear();
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+
+        getDispatcher()->notifyMotion(when, getDeviceId(), mPointerSource, policyFlags,
+                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
     }
 
     // Update state.
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 08cc75e..0ae2ab8 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -252,11 +252,7 @@
                         | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
             status_t status;
             if (!haveTransaction) {
-                status = mSurfaceComposerClient->openTransaction();
-                if (status) {
-                    LOGE("Error %d opening transation to update sprite surface.", status);
-                    break;
-                }
+                SurfaceComposerClient::openGlobalTransaction();
                 haveTransaction = true;
             }
 
@@ -322,10 +318,7 @@
     }
 
     if (haveTransaction) {
-        status_t status = mSurfaceComposerClient->closeTransaction();
-        if (status) {
-            LOGE("Error %d closing transaction to update sprite surface.", status);
-        }
+        SurfaceComposerClient::closeGlobalTransaction();
     }
 
     // If any surfaces were changed, write back the new surface properties to the sprites.
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 8c07e15..5e54d61 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -255,10 +255,7 @@
             
             // Update the kernel timezone information
             // Kernel tracks time offsets as 'minutes west of GMT'
-            int gmtOffset = zone.getRawOffset();
-            if (zone.inDaylightTime(new Date(System.currentTimeMillis()))) {
-                gmtOffset += zone.getDSTSavings();
-            }
+            int gmtOffset = zone.getOffset(System.currentTimeMillis());
             setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
         }
 
@@ -759,9 +756,8 @@
                 // based off of the current Zone gmt offset + userspace tracked
                 // daylight savings information.
                 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
-                int gmtOffset = (zone.getRawOffset() + zone.getDSTSavings()) / 60000;
-
-                setKernelTimezone(mDescriptor, -(gmtOffset));
+                int gmtOffset = zone.getOffset(System.currentTimeMillis());
+                setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
             	scheduleDateChangedEvent();
             }
         }
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index aa3dfa6..8fb6274 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -131,8 +131,6 @@
      */
     private List mNetRequestersPids[];
 
-    private WifiWatchdogService mWifiWatchdogService;
-
     // priority order of the nettrackers
     // (excluding dynamically set mNetworkPreference)
     // TODO - move mNetworkTypePreference into this
@@ -278,6 +276,9 @@
     }
     RadioAttributes[] mRadioAttributes;
 
+    // the set of network types that can only be enabled by system/sig apps
+    List mProtectedNetworks;
+
     public ConnectivityService(
             Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
         if (DBG) log("ConnectivityService starting up");
@@ -381,6 +382,17 @@
             }
         }
 
+        mProtectedNetworks = new ArrayList<Integer>();
+        int[] protectedNetworks = context.getResources().getIntArray(
+                com.android.internal.R.array.config_protectedNetworks);
+        for (int p : protectedNetworks) {
+            if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
+                mProtectedNetworks.add(p);
+            } else {
+                if (DBG) loge("Ignoring protectedNetwork " + p);
+            }
+        }
+
         // high priority first
         mPriorityList = new int[mNetworksDefined];
         {
@@ -432,10 +444,6 @@
                 wifiService.checkAndStartWifi();
                 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
                 wst.startMonitoring(context, mHandler);
-
-                //TODO: as part of WWS refactor, create only when needed
-                mWifiWatchdogService = new WifiWatchdogService(context);
-
                 break;
             case ConnectivityManager.TYPE_MOBILE:
                 mNetTrackers[netType] = new MobileDataStateTracker(netType,
@@ -466,12 +474,10 @@
         INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
 
         mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
-        mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
-                                  !mTethering.isDunRequired()) &&
-                                 (mTethering.getTetherableUsbRegexs().length != 0 ||
+        mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
                                   mTethering.getTetherableWifiRegexs().length != 0 ||
                                   mTethering.getTetherableBluetoothRegexs().length != 0) &&
-                                 mTethering.getUpstreamIfaceRegexs().length != 0);
+                                 mTethering.getUpstreamIfaceTypes().length != 0);
 
         mVpn = new Vpn(mContext, new VpnCallback());
 
@@ -804,6 +810,11 @@
                 usedNetworkType = networkType;
             }
         }
+
+        if (mProtectedNetworks.contains(usedNetworkType)) {
+            enforceConnectivityInternalPermission();
+        }
+
         NetworkStateTracker network = mNetTrackers[usedNetworkType];
         if (network != null) {
             Integer currentPid = new Integer(getCallingPid());
@@ -1014,6 +1025,10 @@
      */
     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
         enforceChangePermission();
+        if (mProtectedNetworks.contains(networkType)) {
+            enforceConnectivityInternalPermission();
+        }
+
         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
             return false;
         }
@@ -1131,7 +1146,8 @@
     }
 
     public void setDataDependency(int networkType, boolean met) {
-        enforceChangePermission();
+        enforceConnectivityInternalPermission();
+
         if (DBG) {
             log("setDataDependency(" + networkType + ", " + met + ")");
         }
@@ -1576,12 +1592,6 @@
                 }
                 addPrivateDnsRoutes(mNetTrackers[netType]);
             }
-
-            /** Notify TetheringService if interface name has been changed. */
-            if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
-                                 Phone.REASON_LINK_PROPERTIES_CHANGED)) {
-                handleTetherIfaceChange(netType);
-            }
         } else {
             if (mNetConfigs[netType].isDefault()) {
                 removeDefaultRoute(mNetTrackers[netType]);
@@ -1600,6 +1610,16 @@
                 }
             }
         }
+
+        // TODO: Temporary notifying upstread change to Tethering.
+        //       @see bug/4455071
+        /** Notify TetheringService if interface name has been changed. */
+        if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
+                             Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+            if (isTetheringSupported()) {
+                mTethering.handleTetherIfaceChange();
+            }
+        }
     }
 
     private void addPrivateDnsRoutes(NetworkStateTracker nt) {
@@ -2025,7 +2045,10 @@
                     break;
                 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
                     info = (NetworkInfo) msg.obj;
-                    handleConnectivityChange(info.getType(), true);
+                    // TODO: Temporary allowing network configuration
+                    //       change not resetting sockets.
+                    //       @see bug/4455071
+                    handleConnectivityChange(info.getType(), false);
                     break;
                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
                     String causedBy = null;
@@ -2412,14 +2435,6 @@
         }
     }
 
-    private void handleTetherIfaceChange(int type) {
-        String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();
-
-        if (isTetheringSupported()) {
-            mTethering.handleTetherIfaceChange(iface);
-        }
-    }
-
     private void log(String s) {
         Slog.d(TAG, s);
     }
diff --git a/services/java/com/android/server/DnsPinger.java b/services/java/com/android/server/DnsPinger.java
new file mode 100644
index 0000000..a7324d9
--- /dev/null
+++ b/services/java/com/android/server/DnsPinger.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Slog;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketTimeoutException;
+import java.util.Collection;
+import java.util.Random;
+
+/**
+ * Performs a simple DNS "ping" by sending a "server status" query packet to the
+ * DNS server. As long as the server replies, we consider it a success.
+ * <p>
+ * We do not use a simple hostname lookup because that could be cached and the
+ * API may not differentiate between a time out and a failure lookup (which we
+ * really care about).
+ * <p>
+ * TODO : More general API. Socket does not bind to specified connection type
+ * TODO : Choice of DNS query location - current looks up www.android.com
+ *
+ * @hide
+ */
+public final class DnsPinger {
+    private static final boolean V = true;
+
+    /** Number of bytes for the query */
+    private static final int DNS_QUERY_BASE_SIZE = 33;
+
+    /** The DNS port */
+    private static final int DNS_PORT = 53;
+
+    /** Used to generate IDs */
+    private static Random sRandom = new Random();
+
+    private ConnectivityManager mConnectivityManager = null;
+    private Context mContext;
+    private int mConnectionType;
+    private InetAddress mDefaultDns;
+
+    private String TAG;
+
+    /**
+     * @param connectionType The connection type from {@link ConnectivityManager}
+     */
+    public DnsPinger(String TAG, Context context, int connectionType) {
+        mContext = context;
+        mConnectionType = connectionType;
+        if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
+            Slog.e(TAG, "Invalid connectionType in constructor: " + connectionType);
+        }
+        this.TAG = TAG;
+
+        mDefaultDns = getDefaultDns();
+    }
+
+    /**
+     * @return The first DNS in the link properties of the specified connection
+     *         type or the default system DNS if the link properties has null
+     *         dns set. Should not be null.
+     */
+    public InetAddress getDns() {
+        if (mConnectivityManager == null) {
+            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
+        }
+
+        LinkProperties curLinkProps = mConnectivityManager.getLinkProperties(mConnectionType);
+        if (curLinkProps == null) {
+            Slog.e(TAG, "getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
+            return mDefaultDns;
+        }
+
+        Collection<InetAddress> dnses = curLinkProps.getDnses();
+        if (dnses == null || dnses.size() == 0) {
+            Slog.v(TAG, "getDns::LinkProps has null dns - returning default");
+            return mDefaultDns;
+        }
+
+        return dnses.iterator().next();
+    }
+
+    private InetAddress getDefaultDns() {
+        String dns = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.DEFAULT_DNS_SERVER);
+        if (dns == null || dns.length() == 0) {
+            dns = mContext.getResources().getString(
+                    com.android.internal.R.string.config_default_dns_server);
+        }
+        try {
+            return NetworkUtils.numericToInetAddress(dns);
+        } catch (IllegalArgumentException e) {
+            Slog.w(TAG, "getDefaultDns::malformed default dns address");
+            return null;
+        }
+    }
+
+    /**
+     * @return time to response. Negative value on error.
+     */
+    public long pingDns(InetAddress dnsAddress, int timeout) {
+        DatagramSocket socket = null;
+        try {
+            socket = new DatagramSocket();
+
+            // Set some socket properties
+            socket.setSoTimeout(timeout);
+
+            byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
+            fillQuery(buf);
+
+            // Send the DNS query
+
+            DatagramPacket packet = new DatagramPacket(buf,
+                    buf.length, dnsAddress, DNS_PORT);
+            long start = SystemClock.elapsedRealtime();
+            socket.send(packet);
+
+            // Wait for reply (blocks for the above timeout)
+            DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
+            socket.receive(replyPacket);
+
+            // If a timeout occurred, an exception would have been thrown. We
+            // got a reply!
+            return SystemClock.elapsedRealtime() - start;
+
+        } catch (SocketTimeoutException e) {
+            // Squelch this exception.
+            return -1;
+        } catch (Exception e) {
+            if (V) {
+                Slog.v(TAG, "DnsPinger.pingDns got socket exception: ", e);
+            }
+            return -2;
+        } finally {
+            if (socket != null) {
+                socket.close();
+            }
+        }
+
+    }
+
+    private static void fillQuery(byte[] buf) {
+
+        /*
+         * See RFC2929 (though the bit tables in there are misleading for us.
+         * For example, the recursion desired bit is the 0th bit for us, but
+         * looking there it would appear as the 7th bit of the byte
+         */
+
+        // Make sure it's all zeroed out
+        for (int i = 0; i < buf.length; i++)
+            buf[i] = 0;
+
+        // Form a query for www.android.com
+
+        // [0-1] bytes are an ID, generate random ID for this query
+        buf[0] = (byte) sRandom.nextInt(256);
+        buf[1] = (byte) sRandom.nextInt(256);
+
+        // [2-3] bytes are for flags.
+        buf[2] = 1; // Recursion desired
+
+        // [4-5] bytes are for the query count
+        buf[5] = 1; // One query
+
+        // [6-7] [8-9] [10-11] are all counts of other fields we don't use
+
+        // [12-15] for www
+        writeString(buf, 12, "www");
+
+        // [16-23] for android
+        writeString(buf, 16, "android");
+
+        // [24-27] for com
+        writeString(buf, 24, "com");
+
+        // [29-30] bytes are for QTYPE, set to 1
+        buf[30] = 1;
+
+        // [31-32] bytes are for QCLASS, set to 1
+        buf[32] = 1;
+    }
+
+    private static void writeString(byte[] buf, int startPos, String string) {
+        int pos = startPos;
+
+        // Write the length first
+        buf[pos++] = (byte) string.length();
+        for (int i = 0; i < string.length(); i++) {
+            buf[pos++] = (byte) string.charAt(i);
+        }
+    }
+}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 8037d7a..14abf80 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -137,6 +137,7 @@
     private static final String NOT_A_SUBTYPE_ID_STR = String.valueOf(NOT_A_SUBTYPE_ID);
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
+    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
 
     final Context mContext;
     final Resources mRes;
@@ -1057,25 +1058,44 @@
         synchronized (mMethodMap) {
             List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
             final int N = imis.size();
-            int count = 0;
+            if (N > 2) return true;
+            if (N < 1) return false;
+            int nonAuxCount = 0;
+            int auxCount = 0;
+            InputMethodSubtype nonAuxSubtype = null;
+            InputMethodSubtype auxSubtype = null;
             for(int i = 0; i < N; ++i) {
                 final InputMethodInfo imi = imis.get(i);
                 final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeListLocked(
                         imi, true);
                 final int subtypeCount = subtypes.size();
                 if (subtypeCount == 0) {
-                    ++count;
+                    ++nonAuxCount;
                 } else {
                     for (int j = 0; j < subtypeCount; ++j) {
-                        if (!subtypes.get(j).isAuxiliary()) {
-                            ++count;
+                        final InputMethodSubtype subtype = subtypes.get(j);
+                        if (!subtype.isAuxiliary()) {
+                            ++nonAuxCount;
+                            nonAuxSubtype = subtype;
+                        } else {
+                            ++auxCount;
+                            auxSubtype = subtype;
                         }
                     }
                 }
-                if (count > 1) return true;
             }
+            if (nonAuxCount > 1 || auxCount > 1) {
+                return true;
+            } else if (nonAuxCount == 1 && auxCount == 1) {
+                if (nonAuxSubtype != null && auxSubtype != null
+                        && nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
+                        && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
+                    return false;
+                }
+                return true;
+            }
+            return false;
         }
-        return false;
     }
 
     @Override
@@ -1621,7 +1641,7 @@
             final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
             if (imi == null) return false;
             final int N = subtypes.length;
-            mFileManager.addInputMethodSubtypes(mCurMethodId, subtypes);
+            mFileManager.addInputMethodSubtypes(imi, subtypes);
             buildInputMethodListLocked(mMethodList, mMethodMap);
             return true;
         }
@@ -2003,25 +2023,26 @@
                 final CharSequence label = imi.loadLabel(pm);
                 if (showSubtypes && enabledSubtypeSet.size() > 0) {
                     final int subtypeCount = imi.getSubtypeCount();
+                    if (DEBUG) {
+                        Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId());
+                    }
                     for (int j = 0; j < subtypeCount; ++j) {
-                        InputMethodSubtype subtype = imi.getSubtypeAt(j);
-                        if (enabledSubtypeSet.contains(String.valueOf(subtype.hashCode()))
-                                && !subtype.isAuxiliary()) {
+                        final InputMethodSubtype subtype = imi.getSubtypeAt(j);
+                        final String subtypeHashCode = String.valueOf(subtype.hashCode());
+                        // We show all enabled IMEs and subtypes when an IME is shown.
+                        if (enabledSubtypeSet.contains(subtypeHashCode)
+                                && (mInputShown || !subtype.isAuxiliary())) {
                             final CharSequence title;
-                            int nameResId = subtype.getNameResId();
-                            String mode = subtype.getMode();
-                            if (nameResId != 0) {
-                                title = TextUtils.concat(subtype.getDisplayName(context,
-                                        imi.getPackageName(), imi.getServiceInfo().applicationInfo),
-                                        (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
-                            } else {
-                                CharSequence language = subtype.getLocale();
-                                // TODO: Use more friendly Title and UI
-                                title = label + "," + (mode == null ? "" : mode) + ","
-                                        + (language == null ? "" : language);
-                            }
+                            final String mode = subtype.getMode();
+                            title = TextUtils.concat(subtype.getDisplayName(context,
+                                    imi.getPackageName(), imi.getServiceInfo().applicationInfo),
+                                    (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
                             imList.add(new Pair<CharSequence, Pair<InputMethodInfo, Integer>>(
                                     title, new Pair<InputMethodInfo, Integer>(imi, j)));
+                            // Removing this subtype from enabledSubtypeSet because we no longer
+                            // need to add an entry of this subtype to imList to avoid duplicated
+                            // entries.
+                            enabledSubtypeSet.remove(subtypeHashCode);
                         }
                     }
                 } else {
@@ -2318,7 +2339,7 @@
                 }
             }
         }
-        ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
+        final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
                 applicableModeAndSubtypesMap.values());
         if (!containsKeyboardSubtype) {
             InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
@@ -2996,17 +3017,23 @@
         }
 
         public void addInputMethodSubtypes(
-                String imiId, InputMethodSubtype[] additionalSubtypes) {
+                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
             synchronized (mMethodMap) {
+                final HashSet<InputMethodSubtype> existingSubtypes =
+                        new HashSet<InputMethodSubtype>();
+                for (int i = 0; i < imi.getSubtypeCount(); ++i) {
+                    existingSubtypes.add(imi.getSubtypeAt(i));
+                }
+
                 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
                 final int N = additionalSubtypes.length;
                 for (int i = 0; i < N; ++i) {
                     final InputMethodSubtype subtype = additionalSubtypes[i];
-                    if (!subtypes.contains(subtype)) {
+                    if (!subtypes.contains(subtype) && !existingSubtypes.contains(subtype)) {
                         subtypes.add(subtype);
                     }
                 }
-                mSubtypesMap.put(imiId, subtypes);
+                mSubtypesMap.put(imi.getId(), subtypes);
                 writeAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile,
                         mMethodMap);
             }
@@ -3113,8 +3140,8 @@
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
                         final String imeSubtypeExtraValue =
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
-                        final boolean isAuxiliary =
-                                Boolean.valueOf(parser.getAttributeValue(null, ATTR_IS_AUXILIARY));
+                        final boolean isAuxiliary = "1".equals(String.valueOf(
+                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
                         final InputMethodSubtype subtype =
                                 new InputMethodSubtype(label, icon, imeSubtypeLocale,
                                         imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d3244ec..54e5432 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1626,6 +1626,30 @@
         }
     }
 
+    public String getSecureContainerFilesystemPath(String id) {
+        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        waitForReady();
+        warnOnNotMounted();
+
+        try {
+            ArrayList<String> rsp = mConnector.doCommand(String.format("asec fspath %s", id));
+            String []tok = rsp.get(0).split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code != VoldResponseCode.AsecPathResult) {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+            return tok[1];
+        } catch (NativeDaemonConnectorException e) {
+            int code = e.getCode();
+            if (code == VoldResponseCode.OpFailedStorageNotFound) {
+                Slog.i(TAG, String.format("Container '%s' not found", id));
+                return null;
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+    }
+
     public void finishMediaUpdate() {
         mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
     }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index a8cb333..adc6570 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -19,6 +19,7 @@
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
+import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -36,6 +37,11 @@
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
 
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -47,6 +53,8 @@
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
 import java.util.concurrent.CountDownLatch;
@@ -64,9 +72,18 @@
     private static final int ADD = 1;
     private static final int REMOVE = 2;
 
+    /** Path to {@code /proc/uid_stat}. */
     @Deprecated
-    private static final File STATS_UIDSTAT = new File("/proc/uid_stat");
-    private static final File STATS_NETFILTER = new File("/proc/net/xt_qtaguid/stats");
+    private final File mProcStatsUidstat;
+    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
+    private final File mProcStatsNetfilter;
+
+    /** {@link #mProcStatsNetfilter} headers. */
+    private static final String KEY_IFACE = "iface";
+    private static final String KEY_TAG_HEX = "acct_tag_hex";
+    private static final String KEY_UID = "uid_tag_int";
+    private static final String KEY_RX = "rx_bytes";
+    private static final String KEY_TX = "tx_bytes";
 
     class NetdResponseCode {
         public static final int InterfaceListResult       = 110;
@@ -101,15 +118,23 @@
 
     private ArrayList<INetworkManagementEventObserver> mObservers;
 
+    /** Set of interfaces with active quotas. */
+    private HashSet<String> mInterfaceQuota = Sets.newHashSet();
+    /** Set of UIDs with active reject rules. */
+    private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
+
     /**
      * Constructs a new NetworkManagementService instance
      *
      * @param context  Binder context for this service
      */
-    private NetworkManagementService(Context context) {
+    private NetworkManagementService(Context context, File procRoot) {
         mContext = context;
         mObservers = new ArrayList<INetworkManagementEventObserver>();
 
+        mProcStatsUidstat = new File(procRoot, "uid_stat");
+        mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats");
+
         if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
             return;
         }
@@ -120,7 +145,8 @@
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        NetworkManagementService service = new NetworkManagementService(context);
+        NetworkManagementService service = new NetworkManagementService(
+                context, new File("/proc/"));
         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
         service.mThread.start();
         if (DBG) Slog.d(TAG, "Awaiting socket connection");
@@ -129,6 +155,12 @@
         return service;
     }
 
+    // @VisibleForTesting
+    public static NetworkManagementService createForTest(Context context, File procRoot) {
+        // TODO: eventually connect with mock netd
+        return new NetworkManagementService(context, procRoot);
+    }
+
     public void registerObserver(INetworkManagementEventObserver obs) {
         Slog.d(TAG, "Registering observer");
         mObservers.add(obs);
@@ -140,12 +172,26 @@
     }
 
     /**
-     * Notify our observers of an interface link status change
+     * Notify our observers of an interface status change
      */
-    private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
+    private void notifyInterfaceStatusChanged(String iface, boolean up) {
         for (INetworkManagementEventObserver obs : mObservers) {
             try {
-                obs.interfaceLinkStatusChanged(iface, link);
+                obs.interfaceStatusChanged(iface, up);
+            } catch (Exception ex) {
+                Slog.w(TAG, "Observer notifier failed", ex);
+            }
+        }
+    }
+
+    /**
+     * Notify our observers of an interface link state change
+     * (typically, an Ethernet cable has been plugged-in or unplugged).
+     */
+    private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
+        for (INetworkManagementEventObserver obs : mObservers) {
+            try {
+                obs.interfaceLinkStateChanged(iface, up);
             } catch (Exception ex) {
                 Slog.w(TAG, "Observer notifier failed", ex);
             }
@@ -206,6 +252,7 @@
                  * Format: "NNN Iface added <name>"
                  *         "NNN Iface removed <name>"
                  *         "NNN Iface changed <name> <up/down>"
+                 *         "NNN Iface linkstatus <name> <up/down>"
                  */
                 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
                     throw new IllegalStateException(
@@ -218,7 +265,10 @@
                     notifyInterfaceRemoved(cooked[3]);
                     return true;
                 } else if (cooked[2].equals("changed") && cooked.length == 5) {
-                    notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
+                    notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
+                    return true;
+                } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
+                    notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
                     return true;
                 }
                 throw new IllegalStateException(
@@ -869,7 +919,7 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
 
-        if (STATS_NETFILTER.exists()) {
+        if (mProcStatsNetfilter.exists()) {
             return getNetworkStatsDetailNetfilter(UID_ALL);
         } else {
             return getNetworkStatsDetailUidstat(UID_ALL);
@@ -877,13 +927,91 @@
     }
 
     @Override
+    public void setInterfaceQuota(String iface, long quota) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        synchronized (mInterfaceQuota) {
+            if (mInterfaceQuota.contains(iface)) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth setiquota ").append(iface).append(" ").append(quota);
+
+            try {
+                // TODO: add support for quota shared across interfaces
+                mConnector.doCommand(command.toString());
+                mInterfaceQuota.add(iface);
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
+    @Override
+    public void removeInterfaceQuota(String iface) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        synchronized (mInterfaceQuota) {
+            if (!mInterfaceQuota.contains(iface)) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth removeiquota ").append(iface);
+
+            try {
+                // TODO: add support for quota shared across interfaces
+                mConnector.doCommand(command.toString());
+                mInterfaceQuota.remove(iface);
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
+    @Override
+    public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        synchronized (mUidRejectOnQuota) {
+            final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
+            if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth");
+            if (rejectOnQuotaInterfaces) {
+                command.append(" addnaughtyapps");
+            } else {
+                command.append(" removenaughtyapps");
+            }
+            command.append(" ").append(uid);
+
+            try {
+                mConnector.doCommand(command.toString());
+                if (rejectOnQuotaInterfaces) {
+                    mUidRejectOnQuota.put(uid, true);
+                } else {
+                    mUidRejectOnQuota.delete(uid);
+                }
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
     public NetworkStats getNetworkStatsUidDetail(int uid) {
         if (Binder.getCallingUid() != uid) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
         }
 
-        if (STATS_NETFILTER.exists()) {
+        if (mProcStatsNetfilter.exists()) {
             return getNetworkStatsDetailNetfilter(uid);
         } else {
             return getNetworkStatsDetailUidstat(uid);
@@ -895,35 +1023,36 @@
      */
     private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) {
         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+        final ArrayList<String> keys = Lists.newArrayList();
+        final ArrayList<String> values = Lists.newArrayList();
+        final HashMap<String, String> parsed = Maps.newHashMap();
 
         BufferedReader reader = null;
         try {
-            reader = new BufferedReader(new FileReader(STATS_NETFILTER));
+            reader = new BufferedReader(new FileReader(mProcStatsNetfilter));
 
-            // assumes format from kernel:
-            // idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes
-
-            // skip first line, which is legend
+            // parse first line as header
             String line = reader.readLine();
-            while ((line = reader.readLine()) != null) {
-                final StringTokenizer t = new StringTokenizer(line);
+            splitLine(line, keys);
 
-                final String idx = t.nextToken();
-                final String iface = t.nextToken();
+            // parse remaining lines
+            while ((line = reader.readLine()) != null) {
+                splitLine(line, values);
+                parseLine(keys, values, parsed);
 
                 try {
-                    // TODO: kernel currently emits tag in upper half of long;
-                    // eventually switch to directly using int.
-                    final int tag = (int) (Long.parseLong(t.nextToken().substring(2), 16) >> 32);
-                    final int uid = Integer.parseInt(t.nextToken());
-                    final long rx = Long.parseLong(t.nextToken());
-                    final long tx = Long.parseLong(t.nextToken());
+                    final String iface = parsed.get(KEY_IFACE);
+                    final int tag = NetworkManagementSocketTagger.kernelToTag(
+                            parsed.get(KEY_TAG_HEX));
+                    final int uid = Integer.parseInt(parsed.get(KEY_UID));
+                    final long rx = Long.parseLong(parsed.get(KEY_RX));
+                    final long tx = Long.parseLong(parsed.get(KEY_TX));
 
                     if (limitUid == UID_ALL || limitUid == uid) {
                         stats.addEntry(iface, uid, tag, rx, tx);
                     }
                 } catch (NumberFormatException e) {
-                    Slog.w(TAG, "problem parsing stats for idx " + idx + ": " + e);
+                    Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
                 }
             }
         } catch (IOException e) {
@@ -945,7 +1074,7 @@
     private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
         final String[] knownUids;
         if (limitUid == UID_ALL) {
-            knownUids = STATS_UIDSTAT.list();
+            knownUids = mProcStatsUidstat.list();
         } else {
             knownUids = new String[] { String.valueOf(limitUid) };
         }
@@ -954,7 +1083,7 @@
                 SystemClock.elapsedRealtime(), knownUids.length);
         for (String uid : knownUids) {
             final int uidInt = Integer.parseInt(uid);
-            final File uidPath = new File(STATS_UIDSTAT, uid);
+            final File uidPath = new File(mProcStatsUidstat, uid);
             final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
             final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
             stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx);
@@ -1022,6 +1151,38 @@
         return getInterfaceThrottle(iface, false);
     }
 
+    @Override
+    public void setBandwidthControlEnabled(boolean enabled) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        mConnector.doCommand(String.format("bandwidth %s", (enabled ? "enable" : "disable")));
+    }
+
+    /**
+     * Split given line into {@link ArrayList}.
+     */
+    private static void splitLine(String line, ArrayList<String> outSplit) {
+        outSplit.clear();
+
+        final StringTokenizer t = new StringTokenizer(line);
+        while (t.hasMoreTokens()) {
+            outSplit.add(t.nextToken());
+        }
+    }
+
+    /**
+     * Zip the two given {@link ArrayList} as key and value pairs into
+     * {@link HashMap}.
+     */
+    private static void parseLine(
+            ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) {
+        outParsed.clear();
+
+        final int size = Math.min(keys.size(), values.size());
+        for (int i = 0; i < size; i++) {
+            outParsed.put(keys.get(i), values.get(i));
+        }
+    }
+
     /**
      * Utility method to read a single plain-text {@link Long} from the given
      * {@link File}, usually from a {@code /proc/} filesystem.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a23bacf..dbfd145 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -209,9 +209,11 @@
                                           bluetoothA2dp);
                 bluetooth.initAfterA2dpRegistration();
 
+                int airplaneModeOn = Settings.System.getInt(mContentResolver,
+                        Settings.System.AIRPLANE_MODE_ON, 0);
                 int bluetoothOn = Settings.Secure.getInt(mContentResolver,
                     Settings.Secure.BLUETOOTH_ON, 0);
-                if (bluetoothOn > 0) {
+                if (airplaneModeOn == 0 && bluetoothOn != 0) {
                     bluetooth.enable();
                 }
             }
@@ -281,7 +283,8 @@
             try {
                 Slog.i(TAG, "NetworkPolicy Service");
                 networkPolicy = new NetworkPolicyManagerService(
-                        context, ActivityManagerService.self(), power, networkStats);
+                        context, ActivityManagerService.self(), power,
+                        networkStats, networkManagement);
                 ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting NetworkPolicy Service", e);
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 7266d7d..d81dfdb 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -179,14 +179,17 @@
             mIface = iface;
         }
 
-        public void interfaceLinkStatusChanged(String iface, boolean link) {
-            if (link) {
+        public void interfaceStatusChanged(String iface, boolean up) {
+            if (up) {
                 if (TextUtils.equals(iface, mIface)) {
                     mHandler.obtainMessage(mMsg).sendToTarget();
                 }
             }
         }
 
+        public void interfaceLinkStateChanged(String iface, boolean up) {
+        }
+
         public void interfaceAdded(String iface) {
             // TODO - an interface added in the UP state should also trigger a StatusChanged
             // notification..
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index cb55451..7725891 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -342,6 +342,7 @@
      * Protected by mWifiStateTracker lock.
      */
     private final WorkSource mTmpWorkSource = new WorkSource();
+    private WifiWatchdogService mWifiWatchdogService;
 
     WifiService(Context context) {
         mContext = context;
@@ -431,6 +432,9 @@
         Slog.i(TAG, "WifiService starting up with Wi-Fi " +
                 (wifiEnabled ? "enabled" : "disabled"));
         setWifiEnabled(wifiEnabled);
+
+        //TODO: as part of WWS refactor, create only when needed
+        mWifiWatchdogService = new WifiWatchdogService(mContext);
     }
 
     private boolean testAndClearWifiSavedState() {
@@ -1155,6 +1159,10 @@
         pw.println();
         pw.println("Locks held:");
         mLocks.dump(pw);
+
+        pw.println();
+        pw.println("WifiWatchdogService dump");
+        mWifiWatchdogService.dump(pw);
     }
 
     private class WifiLock extends DeathRecipient {
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index 56bfbe0..1356e2a 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -23,1428 +23,746 @@
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
-import android.net.LinkProperties;
 import android.net.NetworkInfo;
+import android.net.Uri;
 import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
-import android.net.Uri;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Slog;
 
 import java.io.BufferedInputStream;
-import java.io.InputStream;
 import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
+import java.io.InputStream;
+import java.io.PrintWriter;
 import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
 import java.net.URL;
-import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Random;
 import java.util.Scanner;
 
 /**
  * {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi
  * network with multiple access points. After the framework successfully
- * connects to an access point, the watchdog verifies whether the DNS server is
- * reachable. If not, the watchdog blacklists the current access point, leading
- * to a connection on another access point within the same network.
+ * connects to an access point, the watchdog verifies connectivity by 'pinging'
+ * the configured DNS server using {@link DnsPinger}.
  * <p>
- * The watchdog has a few safeguards:
- * <ul>
- * <li>Only monitor networks with multiple access points
- * <li>Only check at most {@link #getMaxApChecks()} different access points
- * within the network before giving up
+ * On DNS check failure, the BSSID is blacklisted if it is reasonably likely
+ * that another AP might have internet access; otherwise the SSID is disabled.
  * <p>
- * The watchdog checks for connectivity on an access point by ICMP pinging the
- * DNS. There are settings that allow disabling the watchdog, or tweaking the
- * acceptable packet loss (and other various parameters).
- * <p>
- * The core logic of the watchdog is done on the main watchdog thread. Wi-Fi
- * callbacks can come in on other threads, so we must queue messages to the main
- * watchdog thread's handler. Most (if not all) state is only written to from
- * the main thread.
+ * On DNS success, the WatchdogService initiates a walled garden check via an
+ * http get. A browser windows is activated if a walled garden is detected.
  * 
- * {@hide}
+ * @hide
  */
 public class WifiWatchdogService {
-    private static final String TAG = "WifiWatchdogService";
-    private static final boolean V = false;
-    private static final boolean D = true;
+
+    private static final String WWS_TAG = "WifiWatchdogService";
+
+    private static final boolean VDBG = true;
+    private static final boolean DBG = true;
+
+    // Used for verbose logging
+    private String mDNSCheckLogStr;
 
     private Context mContext;
     private ContentResolver mContentResolver;
     private WifiManager mWifiManager;
-    private ConnectivityManager mConnectivityManager;
 
-    /**
-     * The main watchdog thread.
-     */
-    private WifiWatchdogThread mThread;
-    /**
-     * The handler for the main watchdog thread.
-     */
     private WifiWatchdogHandler mHandler;
 
-    private ContentObserver mContentObserver;
+    private DnsPinger mDnsPinger;
+
+    private IntentFilter mIntentFilter;
+    private BroadcastReceiver mBroadcastReceiver;
+    private boolean mBroadcastsEnabled;
+
+    private static final int WIFI_SIGNAL_LEVELS = 4;
 
     /**
-     * The current watchdog state. Only written from the main thread!
+     * Low signal is defined as less than or equal to cut off
      */
-    private WatchdogState mState = WatchdogState.IDLE;
-    /**
-     * The SSID of the network that the watchdog is currently monitoring. Only
-     * touched in the main thread!
-     */
-    private String mSsid;
-    /**
-     * The number of access points in the current network ({@link #mSsid}) that
-     * have been checked. Only touched in the main thread, using getter/setter methods.
-     */
-    private int mBssidCheckCount;
-    /** Whether the current AP check should be canceled. */
-    private boolean mShouldCancel;
+    private static final int LOW_SIGNAL_CUTOFF = 0;
+
+    private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL = 2 * 60 * 1000;
+    private static final long MIN_SINGLE_DNS_CHECK_INTERVAL = 10 * 60 * 1000;
+    private static final long MIN_WALLED_GARDEN_INTERVAL = 15 * 60 * 1000;
+
+    private static final int MAX_CHECKS_PER_SSID = 9;
+    private static final int NUM_DNS_PINGS = 7;
+    private static double MIN_RESPONSE_RATE = 0.50;
+
+    // TODO : Adjust multiple DNS downward to 250 on repeated failure
+    // private static final int MULTI_DNS_PING_TIMEOUT_MS = 250;
+
+    private static final int DNS_PING_TIMEOUT_MS = 800;
+    private static final long DNS_PING_INTERVAL = 250;
+
+    private static final long BLACKLIST_FOLLOWUP_INTERVAL = 15 * 1000;
+
+    private Status mStatus = new Status();
+
+    private static class Status {
+        String bssid = "";
+        String ssid = "";
+
+        HashSet<String> allBssids = new HashSet<String>();
+        int numFullDNSchecks = 0;
+
+        long lastSingleCheckTime = -24 * 60 * 60 * 1000;
+        long lastWalledGardenCheckTime = -24 * 60 * 60 * 1000;
+
+        WatchdogState state = WatchdogState.INACTIVE;
+
+        // Info for dns check
+        int dnsCheckTries = 0;
+        int dnsCheckSuccesses = 0;
+
+        public int signal = -200;
+
+    }
+
+    private enum WatchdogState {
+        /**
+         * Full DNS check in progress
+         */
+        DNS_FULL_CHECK,
+
+        /**
+         * Walled Garden detected, will pop up browser next round.
+         */
+        WALLED_GARDEN_DETECTED,
+
+        /**
+         * DNS failed, will blacklist/disable AP next round
+         */
+        DNS_CHECK_FAILURE,
+
+        /**
+         * Online or displaying walled garden auth page
+         */
+        CHECKS_COMPLETE,
+
+        /**
+         * Watchdog idle, network has been blacklisted or received disconnect
+         * msg
+         */
+        INACTIVE,
+
+        BLACKLISTED_AP
+    }
 
     WifiWatchdogService(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        createThread();
-        
-        // The content observer to listen needs a handler, which createThread creates
+        mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context,
+                ConnectivityManager.TYPE_WIFI);
+
+        HandlerThread handlerThread = new HandlerThread("WifiWatchdogServiceThread");
+        handlerThread.start();
+        mHandler = new WifiWatchdogHandler(handlerThread.getLooper());
+
+        setupNetworkReceiver();
+
+        // The content observer to listen needs a handler, which createThread
+        // creates
         registerForSettingsChanges();
+
+        // Start things off
         if (isWatchdogEnabled()) {
-            registerForWifiBroadcasts();
+            mHandler.sendEmptyMessage(WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT);
         }
-        
-        if (V) {
-            myLogV("WifiWatchdogService: Created");
-        }
+    }
+
+    /**
+     *
+     */
+    private void setupNetworkReceiver() {
+        mBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(
+                            WifiWatchdogHandler.MESSAGE_NETWORK_EVENT,
+                            intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO)
+                            ));
+                } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+                    mHandler.sendEmptyMessage(WifiWatchdogHandler.RSSI_CHANGE_EVENT);
+                } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                    mHandler.sendEmptyMessage(WifiWatchdogHandler.SCAN_RESULTS_AVAILABLE);
+                } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(
+                            WifiWatchdogHandler.WIFI_STATE_CHANGE,
+                            intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 4)));
+                }
+            }
+        };
+
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
     }
 
     /**
      * Observes the watchdog on/off setting, and takes action when changed.
      */
     private void registerForSettingsChanges() {
-        ContentResolver contentResolver = mContext.getContentResolver();
-        contentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), false,
-                mContentObserver = new ContentObserver(mHandler) {
+        ContentObserver contentObserver = new ContentObserver(mHandler) {
             @Override
             public void onChange(boolean selfChange) {
-                if (isWatchdogEnabled()) {
-                    registerForWifiBroadcasts();
-                } else {
-                    unregisterForWifiBroadcasts();
-                    if (mHandler != null) {
-                        mHandler.disableWatchdog();
+                mHandler.sendEmptyMessage((WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT));
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON),
+                false, contentObserver);
+    }
+
+    private void handleNewConnection() {
+        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        String newSsid = wifiInfo.getSSID();
+        String newBssid = wifiInfo.getBSSID();
+
+        if (VDBG) {
+            Slog.v(WWS_TAG, String.format("handleConnected:: old (%s, %s) ==> new (%s, %s)",
+                    mStatus.ssid, mStatus.bssid, newSsid, newBssid));
+        }
+
+        if (TextUtils.isEmpty(newSsid) || TextUtils.isEmpty(newBssid)) {
+            return;
+        }
+
+        if (!TextUtils.equals(mStatus.ssid, newSsid)) {
+            mStatus = new Status();
+            mStatus.ssid = newSsid;
+        }
+
+        mStatus.bssid = newBssid;
+        mStatus.allBssids.add(newBssid);
+        mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS);
+
+        initDnsFullCheck();
+    }
+
+    public void updateRssi() {
+        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        if (!TextUtils.equals(mStatus.ssid, wifiInfo.getSSID()) ||
+                !TextUtils.equals(mStatus.bssid, wifiInfo.getBSSID())) {
+            return;
+        }
+
+        mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS);
+    }
+
+    /**
+     * Single step in state machine
+     */
+    private void handleStateStep() {
+        // Slog.v(WWS_TAG, "handleStateStep:: " + mStatus.state);
+
+        switch (mStatus.state) {
+            case DNS_FULL_CHECK:
+                if (VDBG) {
+                    Slog.v(WWS_TAG, "DNS_FULL_CHECK: " + mDNSCheckLogStr);
+                }
+
+                long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+                        DNS_PING_TIMEOUT_MS);
+
+                mStatus.dnsCheckTries++;
+                if (pingResponseTime >= 0)
+                    mStatus.dnsCheckSuccesses++;
+
+                if (DBG) {
+                    if (pingResponseTime >= 0) {
+                        mDNSCheckLogStr += " | " + pingResponseTime;
+                    } else {
+                        mDNSCheckLogStr += " | " + "x";
                     }
                 }
+
+                switch (currentDnsCheckStatus()) {
+                    case SUCCESS:
+                        if (DBG) {
+                            Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Success");
+                        }
+                        doWalledGardenCheck();
+                        break;
+                    case FAILURE:
+                        if (DBG) {
+                            Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Failure");
+                        }
+                        mStatus.state = WatchdogState.DNS_CHECK_FAILURE;
+                        break;
+                    case INCOMPLETE:
+                        // Taking no action
+                        break;
+                }
+                break;
+            case DNS_CHECK_FAILURE:
+                WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+                if (!mStatus.ssid.equals(wifiInfo.getSSID()) ||
+                        !mStatus.bssid.equals(wifiInfo.getBSSID())) {
+                    Slog.i(WWS_TAG, "handleState DNS_CHECK_FAILURE:: network has changed!");
+                    mStatus.state = WatchdogState.INACTIVE;
+                    break;
+                }
+
+                if (mStatus.numFullDNSchecks >= mStatus.allBssids.size() ||
+                        mStatus.numFullDNSchecks >= MAX_CHECKS_PER_SSID) {
+                    disableAP(wifiInfo);
+                } else {
+                    blacklistAP();
+                }
+                break;
+            case WALLED_GARDEN_DETECTED:
+                popUpBrowser();
+                mStatus.state = WatchdogState.CHECKS_COMPLETE;
+                break;
+            case BLACKLISTED_AP:
+                WifiInfo wifiInfo2 = mWifiManager.getConnectionInfo();
+                if (wifiInfo2.getSupplicantState() != SupplicantState.COMPLETED) {
+                    Slog.d(WWS_TAG,
+                            "handleState::BlacklistedAP - offline, but didn't get disconnect!");
+                    mStatus.state = WatchdogState.INACTIVE;
+                    break;
+                }
+                if (mStatus.bssid.equals(wifiInfo2.getBSSID())) {
+                    Slog.d(WWS_TAG, "handleState::BlacklistedAP - connected to same bssid");
+                    if (!handleSingleDnsCheck()) {
+                        disableAP(wifiInfo2);
+                        break;
+                    }
+                }
+
+                Slog.d(WWS_TAG, "handleState::BlacklistedAP - Simiulating a new connection");
+                handleNewConnection();
+                break;
+        }
+    }
+
+    private void doWalledGardenCheck() {
+        if (!isWalledGardenTestEnabled()) {
+            if (VDBG)
+                Slog.v(WWS_TAG, "Skipping walled garden check - disabled");
+            mStatus.state = WatchdogState.CHECKS_COMPLETE;
+            return;
+        }
+        long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL,
+                mStatus.lastWalledGardenCheckTime);
+        if (waitTime > 0) {
+            if (VDBG) {
+                Slog.v(WWS_TAG, "Skipping walled garden check - wait " +
+                        waitTime + " ms.");
             }
-        });
+            mStatus.state = WatchdogState.CHECKS_COMPLETE;
+            return;
+        }
+
+        mStatus.lastWalledGardenCheckTime = SystemClock.elapsedRealtime();
+        if (isWalledGardenConnection()) {
+            if (DBG)
+                Slog.d(WWS_TAG,
+                        "Walled garden test complete - walled garden detected");
+            mStatus.state = WatchdogState.WALLED_GARDEN_DETECTED;
+        } else {
+            if (DBG)
+                Slog.d(WWS_TAG, "Walled garden test complete - online");
+            mStatus.state = WatchdogState.CHECKS_COMPLETE;
+        }
+    }
+
+    private boolean handleSingleDnsCheck() {
+        mStatus.lastSingleCheckTime = SystemClock.elapsedRealtime();
+        long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+                DNS_PING_TIMEOUT_MS);
+        if (DBG) {
+            Slog.d(WWS_TAG, "Ran a single DNS ping. Response time: " + responseTime);
+        }
+        if (responseTime < 0) {
+            return false;
+        }
+        return true;
+
+    }
+
+    /**
+     * @return Delay in MS before next single DNS check can proceed.
+     */
+    private long timeToNextScheduledDNSCheck() {
+        if (mStatus.signal > LOW_SIGNAL_CUTOFF) {
+            return waitTime(MIN_SINGLE_DNS_CHECK_INTERVAL, mStatus.lastSingleCheckTime);
+        } else {
+            return waitTime(MIN_LOW_SIGNAL_CHECK_INTERVAL, mStatus.lastSingleCheckTime);
+        }
+    }
+
+    /**
+     * Helper to return wait time left given a min interval and last run
+     * 
+     * @param interval minimum wait interval
+     * @param lastTime last time action was performed in
+     *            SystemClock.elapsedRealtime()
+     * @return non negative time to wait
+     */
+    private static long waitTime(long interval, long lastTime) {
+        long wait = interval + lastTime - SystemClock.elapsedRealtime();
+        return wait > 0 ? wait : 0;
+    }
+
+    private void popUpBrowser() {
+        Uri uri = Uri.parse("http://www.google.com");
+        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+        intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+                Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    private void disableAP(WifiInfo info) {
+        // TODO : Unban networks if they had low signal ?
+        Slog.i(WWS_TAG, String.format("Disabling current SSID, %s [bssid %s].  " +
+                "numChecks %d, numAPs %d", mStatus.ssid, mStatus.bssid,
+                mStatus.numFullDNSchecks, mStatus.allBssids.size()));
+        mWifiManager.disableNetwork(info.getNetworkId());
+        mStatus.state = WatchdogState.INACTIVE;
+    }
+
+    private void blacklistAP() {
+        Slog.i(WWS_TAG, String.format("Blacklisting current BSSID %s [ssid %s].  " +
+                "numChecks %d, numAPs %d", mStatus.bssid, mStatus.ssid,
+                mStatus.numFullDNSchecks, mStatus.allBssids.size()));
+
+        mWifiManager.addToBlacklist(mStatus.bssid);
+        mWifiManager.reassociate();
+        mStatus.state = WatchdogState.BLACKLISTED_AP;
+    }
+
+    /**
+     * Checks the scan for new BBIDs using current mSsid
+     */
+    private void updateBssids() {
+        String curSsid = mStatus.ssid;
+        HashSet<String> bssids = mStatus.allBssids;
+        List<ScanResult> results = mWifiManager.getScanResults();
+        int oldNumBssids = bssids.size();
+
+        if (results == null) {
+            if (VDBG) {
+                Slog.v(WWS_TAG, "updateBssids: Got null scan results!");
+            }
+            return;
+        }
+
+        for (ScanResult result : results) {
+            if (result != null && curSsid.equals(result.SSID))
+                bssids.add(result.BSSID);
+        }
+
+        // if (VDBG && bssids.size() - oldNumBssids > 0) {
+        // Slog.v(WWS_TAG,
+        // String.format("updateBssids:: Found %d new APs (total %d) on SSID %s",
+        // bssids.size() - oldNumBssids, bssids.size(), curSsid));
+        // }
+    }
+
+    enum DnsCheckStatus {
+        SUCCESS,
+        FAILURE,
+        INCOMPLETE
+    }
+
+    /**
+     * Computes the current results of the dns check, ends early if outcome is
+     * assured.
+     */
+    private DnsCheckStatus currentDnsCheckStatus() {
+        /**
+         * After a full ping count, if we have more responses than this cutoff,
+         * the outcome is success; else it is 'failure'.
+         */
+        double pingResponseCutoff = MIN_RESPONSE_RATE * NUM_DNS_PINGS;
+        int remainingChecks = NUM_DNS_PINGS - mStatus.dnsCheckTries;
+
+        /**
+         * Our final success count will be at least this big, so we're
+         * guaranteed to succeed.
+         */
+        if (mStatus.dnsCheckSuccesses >= pingResponseCutoff) {
+            return DnsCheckStatus.SUCCESS;
+        }
+
+        /**
+         * Our final count will be at most the current count plus the remaining
+         * pings - we're guaranteed to fail.
+         */
+        if (remainingChecks + mStatus.dnsCheckSuccesses < pingResponseCutoff) {
+            return DnsCheckStatus.FAILURE;
+        }
+
+        return DnsCheckStatus.INCOMPLETE;
+    }
+
+    private void initDnsFullCheck() {
+        if (DBG) {
+            Slog.d(WWS_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
+        }
+        mStatus.numFullDNSchecks++;
+        mStatus.dnsCheckSuccesses = 0;
+        mStatus.dnsCheckTries = 0;
+        mStatus.state = WatchdogState.DNS_FULL_CHECK;
+
+        if (DBG) {
+            mDNSCheckLogStr = String.format("Dns Check %d.  Pinging %s on ssid [%s]: ",
+                    mStatus.numFullDNSchecks, mDnsPinger.getDns(),
+                    mStatus.ssid);
+        }
+    }
+
+    /**
+     * DNS based detection techniques do not work at all hotspots. The one sure
+     * way to check a walled garden is to see if a URL fetch on a known address
+     * fetches the data we expect
+     */
+    private boolean isWalledGardenConnection() {
+        InputStream in = null;
+        HttpURLConnection urlConnection = null;
+        try {
+            URL url = new URL(getWalledGardenUrl());
+            urlConnection = (HttpURLConnection) url.openConnection();
+            in = new BufferedInputStream(urlConnection.getInputStream());
+            Scanner scanner = new Scanner(in);
+            if (scanner.findInLine(getWalledGardenPattern()) != null) {
+                return false;
+            } else {
+                return true;
+            }
+        } catch (IOException e) {
+            return false;
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                }
+            }
+            if (urlConnection != null)
+                urlConnection.disconnect();
+        }
+    }
+
+    /**
+     * There is little logic inside this class, instead methods of the form
+     * "handle___" are called in the main {@link WifiWatchdogService}.
+     */
+    private class WifiWatchdogHandler extends Handler {
+        /**
+         * Major network event, object is NetworkInfo
+         */
+        static final int MESSAGE_NETWORK_EVENT = 1;
+        /**
+         * Change in settings, no object
+         */
+        static final int MESSAGE_CONTEXT_EVENT = 2;
+
+        /**
+         * Change in signal strength
+         */
+        static final int RSSI_CHANGE_EVENT = 3;
+        static final int SCAN_RESULTS_AVAILABLE = 4;
+
+        static final int WIFI_STATE_CHANGE = 5;
+
+        /**
+         * Single step of state machine. One DNS check, or one WalledGarden
+         * check, or one external action. We separate out external actions to
+         * increase chance of detecting that a check failure is caused by change
+         * in network status. Messages should have an arg1 which to sync status
+         * messages.
+         */
+        static final int CHECK_SEQUENCE_STEP = 10;
+        static final int SINGLE_DNS_CHECK = 11;
+
+        /**
+         * @param looper
+         */
+        public WifiWatchdogHandler(Looper looper) {
+            super(looper);
+        }
+
+        boolean singleCheckQueued = false;
+        long queuedSingleDnsCheckArrival;
+
+        /**
+         * Sends a singleDnsCheck message with shortest time - guards against
+         * multiple.
+         */
+        private boolean queueSingleDnsCheck() {
+            long delay = timeToNextScheduledDNSCheck();
+            long newArrival = delay + SystemClock.elapsedRealtime();
+            if (singleCheckQueued && queuedSingleDnsCheckArrival <= newArrival)
+                return true;
+            queuedSingleDnsCheckArrival = newArrival;
+            singleCheckQueued = true;
+            removeMessages(SINGLE_DNS_CHECK);
+            return sendMessageDelayed(obtainMessage(SINGLE_DNS_CHECK), delay);
+        }
+
+        boolean checkSequenceQueued = false;
+        long queuedCheckSequenceArrival;
+
+        /**
+         * Sends a state_machine_step message if the delay requested is lower
+         * than the current delay.
+         */
+        private boolean sendCheckSequenceStep(long delay) {
+            long newArrival = delay + SystemClock.elapsedRealtime();
+            if (checkSequenceQueued && queuedCheckSequenceArrival <= newArrival)
+                return true;
+            queuedCheckSequenceArrival = newArrival;
+            checkSequenceQueued = true;
+            removeMessages(CHECK_SEQUENCE_STEP);
+            return sendMessageDelayed(obtainMessage(CHECK_SEQUENCE_STEP), delay);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case CHECK_SEQUENCE_STEP:
+                    checkSequenceQueued = false;
+                    handleStateStep();
+                    if (mStatus.state == WatchdogState.CHECKS_COMPLETE) {
+                        queueSingleDnsCheck();
+                    } else if (mStatus.state == WatchdogState.DNS_FULL_CHECK) {
+                        sendCheckSequenceStep(DNS_PING_INTERVAL);
+                    } else if (mStatus.state == WatchdogState.BLACKLISTED_AP) {
+                        sendCheckSequenceStep(BLACKLIST_FOLLOWUP_INTERVAL);
+                    } else if (mStatus.state != WatchdogState.INACTIVE) {
+                        sendCheckSequenceStep(0);
+                    }
+                    return;
+                case MESSAGE_NETWORK_EVENT:
+                    if (!mBroadcastsEnabled) {
+                        Slog.e(WWS_TAG,
+                                "MessageNetworkEvent - WatchdogService not enabled... returning");
+                        return;
+                    }
+                    NetworkInfo info = (NetworkInfo) msg.obj;
+                    switch (info.getState()) {
+                        case DISCONNECTED:
+                            mStatus.state = WatchdogState.INACTIVE;
+                            return;
+                        case CONNECTED:
+                            handleNewConnection();
+                            sendCheckSequenceStep(0);
+                    }
+                    return;
+                case SINGLE_DNS_CHECK:
+                    singleCheckQueued = false;
+                    if (mStatus.state != WatchdogState.CHECKS_COMPLETE) {
+                        Slog.d(WWS_TAG, "Single check returning, curState: " + mStatus.state);
+                        break;
+                    }
+
+                    if (!handleSingleDnsCheck()) {
+                        initDnsFullCheck();
+                        sendCheckSequenceStep(0);
+                    } else {
+                        queueSingleDnsCheck();
+                    }
+
+                    break;
+                case RSSI_CHANGE_EVENT:
+                    updateRssi();
+                    if (mStatus.state == WatchdogState.CHECKS_COMPLETE)
+                        queueSingleDnsCheck();
+                    break;
+                case SCAN_RESULTS_AVAILABLE:
+                    updateBssids();
+                    break;
+                case WIFI_STATE_CHANGE:
+                    if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) {
+                        Slog.i(WWS_TAG, "WifiStateDisabling -- Resetting WatchdogState");
+                        mStatus = new Status();
+                    }
+                    break;
+                case MESSAGE_CONTEXT_EVENT:
+                    if (isWatchdogEnabled() && !mBroadcastsEnabled) {
+                        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
+                        mBroadcastsEnabled = true;
+                        Slog.i(WWS_TAG, "WifiWatchdogService enabled");
+                    } else if (!isWatchdogEnabled() && mBroadcastsEnabled) {
+                        mContext.unregisterReceiver(mBroadcastReceiver);
+                        removeMessages(SINGLE_DNS_CHECK);
+                        removeMessages(CHECK_SEQUENCE_STEP);
+                        mBroadcastsEnabled = false;
+                        Slog.i(WWS_TAG, "WifiWatchdogService disabled");
+                    }
+                    break;
+            }
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.print("WatchdogStatus: ");
+        pw.print("State " + mStatus.state);
+        pw.println(", network [" + mStatus.ssid + ", " + mStatus.bssid + "]");
+        pw.print("checkCount " + mStatus.numFullDNSchecks);
+        pw.println(", bssids: " + mStatus.allBssids);
+        pw.print(", hasCheckMessages? " +
+                mHandler.hasMessages(WifiWatchdogHandler.CHECK_SEQUENCE_STEP));
+        pw.println(" hasSingleCheckMessages? " +
+                mHandler.hasMessages(WifiWatchdogHandler.SINGLE_DNS_CHECK));
+        pw.println("DNS check log str: " + mDNSCheckLogStr);
+        pw.println("lastSingleCheck: " + mStatus.lastSingleCheckTime);
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED
+     */
+    private Boolean isWalledGardenTestEnabled() {
+        return Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1;
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL
+     */
+    private String getWalledGardenUrl() {
+        String url = Settings.Secure.getString(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL);
+        if (TextUtils.isEmpty(url))
+            return "http://www.google.com/";
+        return url;
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN
+     */
+    private String getWalledGardenPattern() {
+        String pattern = Settings.Secure.getString(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN);
+        if (TextUtils.isEmpty(pattern))
+            return "<title>.*Google.*</title>";
+        return pattern;
     }
 
     /**
      * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON
      */
     private boolean isWatchdogEnabled() {
-        return Settings.Secure.getInt(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_AP_COUNT
-     */
-    private int getApCount() {
         return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_AP_COUNT, 2);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT
-     */
-    private int getInitialIgnoredPingCount() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT , 2);
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_COUNT
-     */
-    private int getPingCount() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_PING_COUNT, 4);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_TIMEOUT_MS
-     */
-    private int getPingTimeoutMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS, 500);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_DELAY_MS
-     */
-    private int getPingDelayMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS, 250);
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED
-     */
-     private Boolean isWalledGardenTestEnabled() {
-        return Settings.Secure.getInt(mContentResolver,
-                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1;
-     }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL
-     */
-     private String getWalledGardenUrl() {
-        String url = Settings.Secure.getString(mContentResolver,
-                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL);
-        if (TextUtils.isEmpty(url)) return "http://www.google.com/";
-        return url;
-     }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN
-     */
-     private String getWalledGardenPattern() {
-        String pattern = Settings.Secure.getString(mContentResolver,
-                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN);
-        if (TextUtils.isEmpty(pattern)) return "<title>.*Google.*</title>";
-        return pattern;
-     }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE
-     */
-    private int getAcceptablePacketLossPercentage() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, 25);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS
-     */
-    private int getMaxApChecks() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS, 7);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED
-     */
-    private boolean isBackgroundCheckEnabled() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, 1) == 1;
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS
-     */
-    private int getBackgroundCheckDelayMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, 60000);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS
-     */
-    private int getBackgroundCheckTimeoutMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, 1000);
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WATCH_LIST
-     * @return the comma-separated list of SSIDs
-     */
-    private String getWatchList() {
-        return Settings.Secure.getString(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_WATCH_LIST);
-    }
-    
-    /**
-     * Registers to receive the necessary Wi-Fi broadcasts.
-     */
-    private void registerForWifiBroadcasts() {
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        mContext.registerReceiver(mReceiver, intentFilter);
-    }
-
-    /**
-     * Unregisters from receiving the Wi-Fi broadcasts.
-     */
-    private void unregisterForWifiBroadcasts() {
-        mContext.unregisterReceiver(mReceiver);
-    }
-
-    /**
-     * Creates the main watchdog thread, including waiting for the handler to be
-     * created.
-     */
-    private void createThread() {
-        mThread = new WifiWatchdogThread();
-        mThread.start();
-        waitForHandlerCreation();
-    }
-
-    /**
-     * Unregister broadcasts and quit the watchdog thread
-     */
-    //TODO: Change back to running WWS when needed
-//    private void quit() {
-//        unregisterForWifiBroadcasts();
-//        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
-//        mHandler.removeAllActions();
-//        mHandler.getLooper().quit();
-//    }
-
-    /**
-     * Waits for the main watchdog thread to create the handler.
-     */
-    private void waitForHandlerCreation() {
-        synchronized(this) {
-            while (mHandler == null) {
-                try {
-                    // Wait for the handler to be set by the other thread
-                    wait();
-                } catch (InterruptedException e) {
-                    Slog.e(TAG, "Interrupted while waiting on handler.");
-                }
-            }
-        }
-    }
-
-    // Utility methods
-    
-    /**
-     * Logs with the current thread.
-     */
-    private static void myLogV(String message) {
-        Slog.v(TAG, "(" + Thread.currentThread().getName() + ") " + message);
-    }
-    
-    private static void myLogD(String message) {
-        Slog.d(TAG, "(" + Thread.currentThread().getName() + ") " + message);
-    }
-    
-    /**
-     * Gets the first DNS of the current AP.
-     * 
-     * @return The first DNS of the current AP.
-     */
-    private InetAddress getDns() {
-        if (mConnectivityManager == null) {
-            mConnectivityManager = (ConnectivityManager)mContext.getSystemService(
-                    Context.CONNECTIVITY_SERVICE);
-        }
-
-        LinkProperties linkProperties = mConnectivityManager.getLinkProperties(
-                ConnectivityManager.TYPE_WIFI);
-        if (linkProperties == null) return null;
-
-        Collection<InetAddress> dnses = linkProperties.getDnses();
-        if (dnses == null || dnses.size() == 0) return null;
-
-        return dnses.iterator().next();
-    }
-
-    /**
-     * Checks whether the DNS can be reached using multiple attempts according
-     * to the current setting values.
-     * 
-     * @return Whether the DNS is reachable
-     */
-    private boolean checkDnsConnectivity() {
-        InetAddress dns = getDns();
-        if (dns == null) {
-            if (V) {
-                myLogV("checkDnsConnectivity: Invalid DNS, returning false");
-            }
-            return false;
-        }
-
-        if (V) {
-            myLogV("checkDnsConnectivity: Checking " + dns.getHostAddress() + " for connectivity");
-        }
-
-        int numInitialIgnoredPings = getInitialIgnoredPingCount();
-        int numPings = getPingCount();
-        int pingDelay = getPingDelayMs();
-        int acceptableLoss = getAcceptablePacketLossPercentage();
-
-        /** See {@link Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT} */
-        int ignoredPingCounter = 0;
-        int pingCounter = 0;
-        int successCounter = 0;
-
-        // No connectivity check needed
-        if (numPings == 0) {
-            return true;
-        }
-
-        // Do the initial pings that we ignore
-        for (; ignoredPingCounter < numInitialIgnoredPings; ignoredPingCounter++) {
-            if (shouldCancel()) return false;
-
-            boolean dnsAlive = DnsPinger.isDnsReachable(dns, getPingTimeoutMs());
-            if (dnsAlive) {
-                /*
-                 * Successful "ignored" pings are *not* ignored (they count in the total number
-                 * of pings), but failures are really ignored.
-                 */
-
-                // TODO: This is confusing logic and should be rewitten
-                // Here, successful 'ignored' pings are interpreted as a success in the below loop
-                pingCounter++;
-                successCounter++;
-            }
-
-            if (V) {
-                Slog.v(TAG, (dnsAlive ? "  +" : "  Ignored: -"));
-            }
-
-            if (shouldCancel()) return false;
-
-            try {
-                Thread.sleep(pingDelay);
-            } catch (InterruptedException e) {
-                Slog.w(TAG, "Interrupted while pausing between pings", e);
-            }
-        }
-
-        // Do the pings that we use to measure packet loss
-        for (; pingCounter < numPings; pingCounter++) {
-            if (shouldCancel()) return false;
-
-            if (DnsPinger.isDnsReachable(dns, getPingTimeoutMs())) {
-                successCounter++;
-                if (V) {
-                    Slog.v(TAG, "  +");
-                }
-            } else {
-                if (V) {
-                    Slog.v(TAG, "  -");
-                }
-            }
-
-            if (shouldCancel()) return false;
-
-            try {
-                Thread.sleep(pingDelay);
-            } catch (InterruptedException e) {
-                Slog.w(TAG, "Interrupted while pausing between pings", e);
-            }
-        }
-
-        //TODO: Integer division might cause problems down the road...
-        int packetLossPercentage = 100 * (numPings - successCounter) / numPings;
-        if (D) {
-            Slog.d(TAG, packetLossPercentage
-                    + "% packet loss (acceptable is " + acceptableLoss + "%)");
-        }
-
-        return !shouldCancel() && (packetLossPercentage <= acceptableLoss);
-    }
-
-    private boolean backgroundCheckDnsConnectivity() {
-        InetAddress dns = getDns();
-
-        if (dns == null) {
-            if (V) {
-                myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false");
-            }
-            return false;
-        }
-
-        if (V) {
-            myLogV("backgroundCheckDnsConnectivity: Background checking " +
-                    dns.getHostAddress() + " for connectivity");
-        }
-
-        return DnsPinger.isDnsReachable(dns, getBackgroundCheckTimeoutMs());
-    }
-
-    /**
-     * Signals the current action to cancel.
-     */
-    private void cancelCurrentAction() {
-        mShouldCancel = true;
-    }
-    
-    /**
-     * Helper to check whether to cancel. 
-     * 
-     * @return Whether to cancel processing the action.
-     */
-    private boolean shouldCancel() {
-        if (V && mShouldCancel) {
-            myLogV("shouldCancel: Cancelling");
-        }
-        
-        return mShouldCancel;
-    }
-    
-    // Wi-Fi initiated callbacks (could be executed in another thread)
-
-    /**
-     * Called when connected to an AP (this can be the next AP in line, or
-     * it can be a completely different network).
-     * 
-     * @param ssid The SSID of the access point.
-     * @param bssid The BSSID of the access point.
-     */
-    private void onConnected(String ssid, String bssid) {
-        if (V) {
-            myLogV("onConnected: SSID: " + ssid + ", BSSID: " + bssid);
-        }
-
-        /*
-         * The current action being processed by the main watchdog thread is now
-         * stale, so cancel it.
-         */
-        cancelCurrentAction();
-        
-        if ((mSsid == null) || !mSsid.equals(ssid)) {
-            /*
-             * This is a different network than what the main watchdog thread is
-             * processing, dispatch the network change message on the main thread.
-             */
-            mHandler.dispatchNetworkChanged(ssid);
-        }
-        
-        if (requiresWatchdog(ssid, bssid)) {
-            if (D) {
-                myLogD(ssid + " (" + bssid + ") requires the watchdog");
-            }
-
-            // This access point requires a watchdog, so queue the check on the main thread
-            mHandler.checkAp(new AccessPoint(ssid, bssid));
-            
-        } else {
-            if (D) {
-                myLogD(ssid + " (" + bssid + ") does not require the watchdog");
-            }
-
-            // This access point does not require a watchdog, so queue idle on the main thread
-            mHandler.idle();
-        }
-        if (isWalledGardenTestEnabled()) mHandler.checkWalledGarden(ssid);
-    }
-    
-    /**
-     * Called when Wi-Fi is enabled.
-     */
-    private void onEnabled() {
-        cancelCurrentAction();
-        // Queue a hard-reset of the state on the main thread
-        mHandler.reset();
-    }
-    
-    /**
-     * Called when disconnected (or some other event similar to being disconnected).
-     */
-    private void onDisconnected() {
-        if (V) {
-            myLogV("onDisconnected");
-        }
-        
-        /*
-         * Disconnected from an access point, the action being processed by the
-         * watchdog thread is now stale, so cancel it.
-         */
-        cancelCurrentAction();
-        // Dispatch the disconnected to the main watchdog thread
-        mHandler.dispatchDisconnected();
-        // Queue the action to go idle
-        mHandler.idle();
-    }
-
-    /**
-     * Checks whether an access point requires watchdog monitoring.
-     * 
-     * @param ssid The SSID of the access point.
-     * @param bssid The BSSID of the access point.
-     * @return Whether the access point/network should be monitored by the
-     *         watchdog.
-     */
-    private boolean requiresWatchdog(String ssid, String bssid) {
-        if (V) {
-            myLogV("requiresWatchdog: SSID: " + ssid + ", BSSID: " + bssid);
-        }
-        
-        WifiInfo info = null;
-        if (ssid == null) {
-            /*
-             * This is called from a Wi-Fi callback, so assume the WifiInfo does
-             * not have stale data.
-             */
-            info = mWifiManager.getConnectionInfo();
-            ssid = info.getSSID();
-            if (ssid == null) {
-                // It's still null, give up
-                if (V) {
-                    Slog.v(TAG, "  Invalid SSID, returning false");
-                }
-                return false;
-            }
-        }
-        
-        if (TextUtils.isEmpty(bssid)) {
-            // Similar as above
-            if (info == null) {
-                info = mWifiManager.getConnectionInfo();
-            }
-            bssid = info.getBSSID();
-            if (TextUtils.isEmpty(bssid)) {
-                // It's still null, give up
-                if (V) {
-                    Slog.v(TAG, "  Invalid BSSID, returning false");
-                }
-                return false;
-            }
-        }
-
-        if (!isOnWatchList(ssid)) {
-            if (V) {
-                Slog.v(TAG, "  SSID not on watch list, returning false");
-            }
-            return false;
-        }
-
-        // The watchdog only monitors networks with multiple APs
-        if (!hasRequiredNumberOfAps(ssid)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private boolean isOnWatchList(String ssid) {
-        String watchList;
-
-        if (ssid == null || (watchList = getWatchList()) == null) {
-            return false;
-        }
-
-        String[] list = watchList.split(" *, *");
-
-        for (String name : list) {
-            if (ssid.equals(name)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-    
-    /**
-     * Checks if the current scan results have multiple access points with an SSID.
-     * 
-     * @param ssid The SSID to check.
-     * @return Whether the SSID has multiple access points.
-     */
-    private boolean hasRequiredNumberOfAps(String ssid) {
-        List<ScanResult> results = mWifiManager.getScanResults();
-        if (results == null) {
-            if (V) {
-                myLogV("hasRequiredNumberOfAps: Got null scan results, returning false");
-            }
-            return false;
-        }
-        
-        int numApsRequired = getApCount();
-        int numApsFound = 0;
-        int resultsSize = results.size();
-        for (int i = 0; i < resultsSize; i++) {
-            ScanResult result = results.get(i);
-            if (result == null) continue;
-            if (result.SSID == null) continue;
-            
-            if (result.SSID.equals(ssid)) {
-                numApsFound++;
-                
-                if (numApsFound >= numApsRequired) {
-                    if (V) {
-                        myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning true");
-                    }
-                    return true;
-                }
-            }
-        }
-        
-        if (V) {
-            myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning false");
-        }
-        return false;
-    }
-    
-    // Watchdog logic (assume all of these methods will be in our main thread)
-    
-    /**
-     * Handles a Wi-Fi network change (for example, from networkA to networkB).
-     */
-    private void handleNetworkChanged(String ssid) {
-        // Set the SSID being monitored to the new SSID 
-        mSsid = ssid;
-        // Set various state to that when being idle 
-        setIdleState(true);
-    }
-    
-    /**
-     * Handles checking whether an AP is a "good" AP.  If not, it will be blacklisted.
-     * 
-     * @param ap The access point to check.
-     */
-    private void handleCheckAp(AccessPoint ap) {
-        // Reset the cancel state since this is the entry point of this action
-        mShouldCancel = false;
-        
-        if (V) {
-            myLogV("handleCheckAp: AccessPoint: " + ap);
-        }
-        
-        // Make sure we are not sleeping
-        if (mState == WatchdogState.SLEEP) {
-            if (V) {
-                Slog.v(TAG, "  Sleeping (in " + mSsid + "), so returning");
-            }
-            return;
-        }
-        
-        mState = WatchdogState.CHECKING_AP;
-        
-        /*
-         * Checks to make sure we haven't exceeded the max number of checks
-         * we're allowed per network
-         */
-        incrementBssidCheckCount();
-        if (getBssidCheckCount() > getMaxApChecks()) {
-            if (V) {
-                Slog.v(TAG, "  Passed the max attempts (" + getMaxApChecks()
-                        + "), going to sleep for " + mSsid);
-            }
-            mHandler.sleep(mSsid);
-            return;
-        }
-
-        // Do the check
-        boolean isApAlive = checkDnsConnectivity();
-        
-        if (V) {
-            Slog.v(TAG, "  Is it alive: " + isApAlive);
-        }
-
-        // Take action based on results
-        if (isApAlive) {
-            handleApAlive(ap);
-        } else {
-            handleApUnresponsive(ap);
-        }
-    }
-
-    /**
-     * Handles the case when an access point is alive.
-     * 
-     * @param ap The access point.
-     */
-    private void handleApAlive(AccessPoint ap) {
-        // Check whether we are stale and should cancel
-        if (shouldCancel()) return;
-        // We're satisfied with this AP, so go idle
-        setIdleState(false);
-        
-        if (D) {
-            myLogD("AP is alive: " + ap.toString());
-        }
-        
-        // Queue the next action to be a background check
-        mHandler.backgroundCheckAp(ap);
-    }
-    
-    /**
-     * Handles an unresponsive AP by blacklisting it.
-     * 
-     * @param ap The access point.
-     */
-    private void handleApUnresponsive(AccessPoint ap) {
-        // Check whether we are stale and should cancel
-        if (shouldCancel()) return;
-        // This AP is "bad", switch to another
-        mState = WatchdogState.SWITCHING_AP;
-
-        if (D) {
-            myLogD("AP is dead: " + ap.toString());
-        }
-        
-        // Black list this "bad" AP, this will cause an attempt to connect to another
-        blacklistAp(ap.bssid);
-        // Initiate an association to an alternate AP
-        mWifiManager.reassociate();
-    }
-
-    private void blacklistAp(String bssid) {
-        if (TextUtils.isEmpty(bssid)) {
-            return;
-        }
-        
-        // Before taking action, make sure we should not cancel our processing
-        if (shouldCancel()) return;
-        
-        mWifiManager.addToBlacklist(bssid);
-
-        if (D) {
-            myLogD("Blacklisting " + bssid);
-        }
-    }
-
-    /**
-     * Handles a single background check. If it fails, it should trigger a
-     * normal check. If it succeeds, it should queue another background check.
-     * 
-     * @param ap The access point to do a background check for. If this is no
-     *        longer the current AP, it is okay to return without any
-     *        processing.
-     */
-    private void handleBackgroundCheckAp(AccessPoint ap) {
-        // Reset the cancel state since this is the entry point of this action
-        mShouldCancel = false;
-        
-        if (V) {
-            myLogV("handleBackgroundCheckAp: AccessPoint: " + ap);
-        }
-        
-        // Make sure we are not sleeping
-        if (mState == WatchdogState.SLEEP) {
-            if (V) {
-                Slog.v(TAG, "  handleBackgroundCheckAp: Sleeping (in " + mSsid + "), so returning");
-            }
-            return;
-        }
-        
-        // Make sure the AP we're supposed to be background checking is still the active one
-        WifiInfo info = mWifiManager.getConnectionInfo();
-        if (info.getSSID() == null || !info.getSSID().equals(ap.ssid)) {
-            if (V) {
-                myLogV("handleBackgroundCheckAp: We are no longer connected to "
-                        + ap + ", and instead are on " + info);
-            }
-            return;
-        }
-        
-        if (info.getBSSID() == null || !info.getBSSID().equals(ap.bssid)) {
-            if (V) {
-                myLogV("handleBackgroundCheckAp: We are no longer connected to "
-                        + ap + ", and instead are on " + info);
-            }
-            return;
-        }
-
-        // Do the check
-        boolean isApAlive = backgroundCheckDnsConnectivity();
-        
-        if (V && !isApAlive) {
-            Slog.v(TAG, "  handleBackgroundCheckAp: Is it alive: " + isApAlive);
-        }
-
-        if (shouldCancel()) {
-            return;
-        }
-        
-        // Take action based on results
-        if (isApAlive) {
-            // Queue another background check
-            mHandler.backgroundCheckAp(ap);
-            
-        } else {
-            if (D) {
-                myLogD("Background check failed for " + ap.toString());
-            }
-            
-            // Queue a normal check, so it can take proper action
-            mHandler.checkAp(ap);
-        }
-    }
-    
-    /**
-     * Handles going to sleep for this network. Going to sleep means we will not
-     * monitor this network anymore.
-     * 
-     * @param ssid The network that will not be monitored anymore.
-     */
-    private void handleSleep(String ssid) {
-        // Make sure the network we're trying to sleep in is still the current network
-        if (ssid != null && ssid.equals(mSsid)) {
-            mState = WatchdogState.SLEEP;
-
-            if (D) {
-                myLogD("Going to sleep for " + ssid);
-            }
-            
-            /*
-             * Before deciding to go to sleep, we may have checked a few APs
-             * (and blacklisted them). Clear the blacklist so the AP with best
-             * signal is chosen.
-             */
-            mWifiManager.clearBlacklist();
-            
-            if (V) {
-                myLogV("handleSleep: Set state to SLEEP and cleared blacklist");
-            }
-        }
-    }
-
-    /**
-     * Handles an access point disconnection.
-     */
-    private void handleDisconnected() {
-        /*
-         * We purposefully do not change mSsid to null. This is to handle
-         * disconnected followed by connected better (even if there is some
-         * duration in between). For example, if the watchdog went to sleep in a
-         * network, and then the phone goes to sleep, when the phone wakes up we
-         * still want to be in the sleeping state. When the phone went to sleep,
-         * we would have gotten a disconnected event which would then set mSsid
-         * = null. This is bad, since the following connect would cause us to do
-         * the "network is good?" check all over again. */
-        
-        /* 
-         * Set the state as if we were idle (don't come out of sleep, only
-         * hard reset and network changed should do that.
-         */
-        setIdleState(false);
-    }
-
-    /**
-     * Handles going idle. Idle means we are satisfied with the current state of
-     * things, but if a new connection occurs we'll re-evaluate.
-     */
-    private void handleIdle() {
-        // Reset the cancel state since this is the entry point for this action
-        mShouldCancel = false;
-        
-        if (V) {
-            myLogV("handleSwitchToIdle");
-        }
-        
-        // If we're sleeping, don't do anything
-        if (mState == WatchdogState.SLEEP) {
-            Slog.v(TAG, "  Sleeping (in " + mSsid + "), so returning");
-            return;
-        }
-        
-        // Set the idle state
-        setIdleState(false);
-        
-        if (V) {
-            Slog.v(TAG, "  Set state to IDLE");
-        }
-    }
-    
-    /**
-     * Sets the state as if we are going idle.
-     */
-    private void setIdleState(boolean forceIdleState) {
-        // Setting idle state does not kick us out of sleep unless the forceIdleState is set
-        if (forceIdleState || (mState != WatchdogState.SLEEP)) {
-            mState = WatchdogState.IDLE;
-        }
-        resetBssidCheckCount();
-    }
-
-    /**
-     * Handles a hard reset. A hard reset is rarely used, but when used it
-     * should revert anything done by the watchdog monitoring.
-     */
-    private void handleReset() {
-        mWifiManager.clearBlacklist();
-        setIdleState(true);
-    }
-    
-    // Inner classes
-
-    /**
-     * Possible states for the watchdog to be in.
-     */
-    private static enum WatchdogState {
-        /** The watchdog is currently idle, but it is still responsive to future AP checks in this network. */
-        IDLE,
-        /** The watchdog is sleeping, so it will not try any AP checks for the network. */
-        SLEEP,
-        /** The watchdog is currently checking an AP for connectivity. */
-        CHECKING_AP,
-        /** The watchdog is switching to another AP in the network. */
-        SWITCHING_AP
-    }
-
-    private int getBssidCheckCount() {
-        return mBssidCheckCount;
-    }
-
-    private void incrementBssidCheckCount() {
-        mBssidCheckCount++;
-    }
-
-    private void resetBssidCheckCount() {
-        this.mBssidCheckCount = 0;
-    }
-
-    /**
-     * The main thread for the watchdog monitoring. This will be turned into a
-     * {@link Looper} thread.
-     */
-    private class WifiWatchdogThread extends Thread {
-        WifiWatchdogThread() {
-            super("WifiWatchdogThread");
-        }
-        
-        @Override
-        public void run() {
-            // Set this thread up so the handler will work on it
-            Looper.prepare();
-            
-            synchronized(WifiWatchdogService.this) {
-                mHandler = new WifiWatchdogHandler();
-
-                // Notify that the handler has been created
-                WifiWatchdogService.this.notify();
-            }
-            
-            // Listen for messages to the handler
-            Looper.loop();
-        }
-    }
-
-    /**
-     * The main thread's handler. There are 'actions', and just general 
-     * 'messages'. There should only ever be one 'action' in the queue (aside
-     * from the one being processed, if any). There may be multiple messages in
-     * the queue. So, actions are replaced by more recent actions, where as
-     * messages will be executed for sure. Messages end up being used to just
-     * change some state, and not really take any action.
-     * <p>
-     * There is little logic inside this class, instead methods of the form
-     * "handle___" are called in the main {@link WifiWatchdogService}.
-     */
-    private class WifiWatchdogHandler extends Handler {
-        /** Check whether the AP is "good".  The object will be an {@link AccessPoint}. */
-        static final int ACTION_CHECK_AP = 1;
-        /** Go into the idle state. */
-        static final int ACTION_IDLE = 2;
-        /**
-         * Performs a periodic background check whether the AP is still "good".
-         * The object will be an {@link AccessPoint}.
-         */
-        static final int ACTION_BACKGROUND_CHECK_AP = 3;
-        /** Check whether the connection is a walled garden */
-        static final int ACTION_CHECK_WALLED_GARDEN = 4;
-
-        /**
-         * Go to sleep for the current network. We are conservative with making
-         * this a message rather than action. We want to make sure our main
-         * thread sees this message, but if it were an action it could be
-         * removed from the queue and replaced by another action. The main
-         * thread will ensure when it sees the message that the state is still
-         * valid for going to sleep.
-         * <p>
-         * For an explanation of sleep, see {@link android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS}.
-         */
-        static final int MESSAGE_SLEEP = 101;
-        /** Disables the watchdog. */
-        static final int MESSAGE_DISABLE_WATCHDOG = 102;
-        /** The network has changed. */
-        static final int MESSAGE_NETWORK_CHANGED = 103;
-        /** The current access point has disconnected. */
-        static final int MESSAGE_DISCONNECTED = 104;
-        /** Performs a hard-reset on the watchdog state. */
-        static final int MESSAGE_RESET = 105;
-
-        /* Walled garden detection */
-        private String mLastSsid;
-        private long mLastTime;
-        private final long MIN_WALLED_GARDEN_TEST_INTERVAL = 15 * 60 * 1000; //15 minutes
-
-        void checkWalledGarden(String ssid) {
-            sendMessage(obtainMessage(ACTION_CHECK_WALLED_GARDEN, ssid));
-        }
-
-        void checkAp(AccessPoint ap) {
-            removeAllActions();
-            sendMessage(obtainMessage(ACTION_CHECK_AP, ap));
-        }
-        
-        void backgroundCheckAp(AccessPoint ap) {
-            if (!isBackgroundCheckEnabled()) return;
-            
-            removeAllActions();
-            sendMessageDelayed(obtainMessage(ACTION_BACKGROUND_CHECK_AP, ap),
-                    getBackgroundCheckDelayMs());
-        }
-        
-        void idle() {
-            removeAllActions();
-            sendMessage(obtainMessage(ACTION_IDLE));
-        }
-        
-        void sleep(String ssid) {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_SLEEP, ssid));
-        }
-        
-        void disableWatchdog() {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_DISABLE_WATCHDOG));
-        }
-        
-        void dispatchNetworkChanged(String ssid) {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_NETWORK_CHANGED, ssid));
-        }
-
-        void dispatchDisconnected() {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_DISCONNECTED));
-        }
-
-        void reset() {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_RESET));
-        }
-        
-        private void removeAllActions() {
-            removeMessages(ACTION_CHECK_AP);
-            removeMessages(ACTION_IDLE);
-            removeMessages(ACTION_BACKGROUND_CHECK_AP);
-        }
-        
-        @Override
-        public void handleMessage(Message msg) {
-            if (V) {
-                myLogV("handleMessage: " + msg.what);
-            }
-            switch (msg.what) {
-                case MESSAGE_NETWORK_CHANGED:
-                    handleNetworkChanged((String) msg.obj);
-                    break;
-                case ACTION_CHECK_AP:
-                    handleCheckAp((AccessPoint) msg.obj);
-                    break;
-                case ACTION_BACKGROUND_CHECK_AP:
-                    handleBackgroundCheckAp((AccessPoint) msg.obj);
-                    break;
-                case ACTION_CHECK_WALLED_GARDEN:
-                    handleWalledGardenCheck((String) msg.obj);
-                    break;
-                case MESSAGE_SLEEP:
-                    handleSleep((String) msg.obj);
-                    break;
-                case ACTION_IDLE:
-                    handleIdle();
-                    break;
-                case MESSAGE_DISABLE_WATCHDOG:
-                    handleIdle();
-                    break;
-                case MESSAGE_DISCONNECTED:
-                    handleDisconnected();
-                    break;
-                case MESSAGE_RESET:
-                    handleReset();
-                    break;
-            }
-        }
-
-        /**
-         * DNS based detection techniques do not work at all hotspots. The one sure way to check
-         * a walled garden is to see if a URL fetch on a known address fetches the data we
-         * expect
-         */
-        private boolean isWalledGardenConnection() {
-            InputStream in = null;
-            HttpURLConnection  urlConnection = null;
-            try {
-                URL url = new URL(getWalledGardenUrl());
-                urlConnection = (HttpURLConnection) url.openConnection();
-                in = new BufferedInputStream(urlConnection.getInputStream());
-                Scanner scanner = new Scanner(in);
-                if (scanner.findInLine(getWalledGardenPattern()) != null) {
-                    return false;
-                } else {
-                    return true;
-                }
-            } catch (IOException e) {
-                return false;
-            } finally {
-                if (in != null) {
-                    try {
-                        in.close();
-                    } catch (IOException e) {
-                    }
-                }
-                if (urlConnection != null) urlConnection.disconnect();
-            }
-        }
-
-        private void handleWalledGardenCheck(String ssid) {
-            long currentTime = System.currentTimeMillis();
-            //Avoid a walled garden test on the same network if one was already done
-            //within MIN_WALLED_GARDEN_TEST_INTERVAL. This will handle scenarios where
-            //there are frequent network disconnections
-            if (ssid.equals(mLastSsid) &&
-                    (currentTime - mLastTime) < MIN_WALLED_GARDEN_TEST_INTERVAL) {
-                return;
-            }
-
-            mLastTime = currentTime;
-            mLastSsid = ssid;
-
-            if (isWalledGardenConnection()) {
-                Uri uri = Uri.parse("http://www.google.com");
-                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
-                intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
-                        Intent.FLAG_ACTIVITY_NEW_TASK);
-                mContext.startActivity(intent);
-            }
-        }
-    }
-
-    /**
-     * Receives Wi-Fi broadcasts.
-     * <p>
-     * There is little logic in this class, instead methods of the form "on___"
-     * are called in the {@link WifiWatchdogService}.
-     */
-    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-                handleNetworkStateChanged(
-                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO));
-            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                        WifiManager.WIFI_STATE_UNKNOWN));
-            }
-        }
-
-        private void handleNetworkStateChanged(NetworkInfo info) {
-            if (V) {
-                myLogV("Receiver.handleNetworkStateChanged: NetworkInfo: "
-                        + info);
-            }
-            
-            switch (info.getState()) {
-                case CONNECTED:
-                    WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-                    if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) {
-                        if (V) {
-                            myLogV("handleNetworkStateChanged: Got connected event but SSID or BSSID are null. SSID: "
-                                + wifiInfo.getSSID()
-                                + ", BSSID: "
-                                + wifiInfo.getBSSID() + ", ignoring event");
-                        }
-                        return;
-                    }
-                    onConnected(wifiInfo.getSSID(), wifiInfo.getBSSID());
-                    break;
-
-                case DISCONNECTED:
-                    onDisconnected();
-                    break;
-            }
-        }
-
-        private void handleWifiStateChanged(int wifiState) {
-            if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
-                onDisconnected();
-            } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
-                onEnabled();
-            }
-        }
-    };
-
-    /**
-     * Describes an access point by its SSID and BSSID.
-     *
-     */
-    private static class AccessPoint {
-        String ssid;
-        String bssid;
-        
-        /**
-         * @param ssid cannot be null
-         * @param bssid cannot be null
-         */
-        AccessPoint(String ssid, String bssid) {
-            if (ssid == null || bssid == null) {
-                Slog.e(TAG, String.format("(%s) INVALID ACCESSPOINT: (%s, %s)",
-                        Thread.currentThread().getName(),ssid,bssid));
-            }
-            this.ssid = ssid;
-            this.bssid = bssid;
-        }
-        
-        @Override
-        public boolean equals(Object o) {
-            if (!(o instanceof AccessPoint)) return false;
-            AccessPoint otherAp = (AccessPoint) o;
-
-            // Either we both have a null, or our SSIDs and BSSIDs are equal
-            return ssid.equals(otherAp.ssid) && bssid.equals(otherAp.bssid);
-        }
-        
-        @Override
-        public int hashCode() {
-            return ssid.hashCode() + bssid.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return ssid + " (" + bssid + ")";
-        }
-    }
-
-    /**
-     * Performs a simple DNS "ping" by sending a "server status" query packet to
-     * the DNS server. As long as the server replies, we consider it a success.
-     * <p>
-     * We do not use a simple hostname lookup because that could be cached and
-     * the API may not differentiate between a time out and a failure lookup
-     * (which we really care about).
-     */
-    private static class DnsPinger {
-        
-        /** Number of bytes for the query */
-        private static final int DNS_QUERY_BASE_SIZE = 33;
-        
-        /** The DNS port */
-        private static final int DNS_PORT = 53;
-        
-        /** Used to generate IDs */
-        private static Random sRandom = new Random();
-
-        static boolean isDnsReachable(InetAddress dnsAddress, int timeout) {
-            DatagramSocket socket = null;
-            try {
-                socket = new DatagramSocket();
-
-                // Set some socket properties
-                socket.setSoTimeout(timeout);
-
-                byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
-                fillQuery(buf);
-
-                // Send the DNS query
-
-                DatagramPacket packet = new DatagramPacket(buf,
-                        buf.length, dnsAddress, DNS_PORT);
-                socket.send(packet);
-
-                // Wait for reply (blocks for the above timeout)
-                DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
-                socket.receive(replyPacket);
-
-                // If a timeout occurred, an exception would have been thrown.  We got a reply!
-                return true;
-
-            } catch (SocketException e) {
-                if (V) {
-                    Slog.v(TAG, "DnsPinger.isReachable received SocketException", e);
-                }
-                return false;
-
-            } catch (UnknownHostException e) {
-                if (V) {
-                    Slog.v(TAG, "DnsPinger.isReachable is unable to resolve the DNS host", e);
-                }
-                return false;
-
-            } catch (SocketTimeoutException e) {
-                return false;
-                
-            } catch (IOException e) {
-                if (V) {
-                    Slog.v(TAG, "DnsPinger.isReachable got an IOException", e);
-                }
-                return false;
-                
-            } catch (Exception e) {
-                if (V) {
-                    Slog.d(TAG, "DnsPinger.isReachable got an unknown exception", e);
-                }
-                return false;
-            } finally {
-                if (socket != null) {
-                    socket.close();
-                }
-            }
-        }
-        
-        private static void fillQuery(byte[] buf) {
-
-            /*
-             * See RFC2929 (though the bit tables in there are misleading for
-             * us. For example, the recursion desired bit is the 0th bit for us,
-             * but looking there it would appear as the 7th bit of the byte
-             */
-
-            // Make sure it's all zeroed out
-            for (int i = 0; i < buf.length; i++) buf[i] = 0;
-
-            // Form a query for www.android.com
-            
-            // [0-1] bytes are an ID, generate random ID for this query
-            buf[0] = (byte) sRandom.nextInt(256); 
-            buf[1] = (byte) sRandom.nextInt(256); 
-            
-            // [2-3] bytes are for flags.
-            buf[2] = 1; // Recursion desired
-
-            // [4-5] bytes are for the query count
-            buf[5] = 1; // One query 
-            
-            // [6-7] [8-9] [10-11] are all counts of other fields we don't use
-
-            // [12-15] for www
-            writeString(buf, 12, "www");
-            
-            // [16-23] for android
-            writeString(buf, 16, "android");
-            
-            // [24-27] for com
-            writeString(buf, 24, "com");
-            
-            // [29-30] bytes are for QTYPE, set to 1 
-            buf[30] = 1;
-
-            // [31-32] bytes are for QCLASS, set to 1 
-            buf[32] = 1;
-        }
-        
-        private static void writeString(byte[] buf, int startPos, String string) {
-            int pos = startPos;
-            
-            // Write the length first
-            buf[pos++] = (byte) string.length();
-            for (int i = 0; i < string.length(); i++) {
-                buf[pos++] = (byte) string.charAt(i);
-            }
-        }
+                Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
     }
 }
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index a9dfb22..10dd924 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -549,6 +550,26 @@
     private void notifyEventListenerLocked(Service service, int eventType) {
         IEventListener listener = service.mServiceInterface;
         AccessibilityEvent event = service.mPendingEvents.get(eventType);
+
+        // Check for null here because there is a concurrent scenario in which this
+        // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
+        // which posts a message for dispatching an event. 2) The message is pulled
+        // from the queue by the handler on the service thread and the latter is
+        // just about to acquire the lock and call this method. 3) Now another binder
+        // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
+        // so the service thread waits for the lock; 4) The binder thread replaces
+        // the event with a more recent one (assume the same event type) and posts a
+        // dispatch request releasing the lock. 5) Now the main thread is unblocked and
+        // dispatches the event which is removed from the pending ones. 6) And ... now
+        // the service thread handles the last message posted by the last binder call
+        // but the event is already dispatched and hence looking it up in the pending
+        // ones yields null. This check is much simpler that keeping count for each
+        // event type of each service to catch such a scenario since only one message
+        // is processed at a time.
+        if (event == null) {
+            return;
+        }
+
         service.mPendingEvents.remove(eventType);
         try {
             if (mSecurityPolicy.canRetrieveWindowContent(service)) {
@@ -814,6 +835,8 @@
 
         final AtomicInteger mInteractionIdCounter = new AtomicInteger();
 
+        final Rect mTempBounds = new Rect();
+
         // the events pending events to be dispatched to this service
         final SparseArray<AccessibilityEvent> mPendingEvents =
             new SparseArray<AccessibilityEvent>();
@@ -932,9 +955,10 @@
                 AccessibilityNodeInfo info = mCallback.getFindAccessibilityNodeInfoResultAndClear(
                         interactionId);
                 if (info != null) {
+                    applyCompatibilityScaleIfNeeded(info);
                     info.setConnection(this);
+                    info.setSealed(true);
                 }
-                info.setSealed(true);
                 return info;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -979,6 +1003,7 @@
                     final int infoCount = infos.size();
                     for (int i = 0; i < infoCount; i++) {
                         AccessibilityNodeInfo info = infos.get(i);
+                        applyCompatibilityScaleIfNeeded(info);
                         info.setConnection(this);
                         info.setSealed(true);
                     }
@@ -1019,6 +1044,7 @@
                 AccessibilityNodeInfo info =
                      mCallback.getFindAccessibilityNodeInfoResultAndClear(interactionId);
                 if (info != null) {
+                    applyCompatibilityScaleIfNeeded(info);
                     info.setConnection(this);
                     info.setSealed(true);
                 }
@@ -1093,6 +1119,24 @@
             }
             return mWindowIdToInteractionConnectionMap.get(windowId);
         }
+
+        private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info) {
+            IBinder windowToken = mWindowIdToWindowTokenMap.get(info.getWindowId());
+            final float scale = mWindowManagerService.getWindowCompatibilityScale(windowToken);
+
+            if (scale == 1.0f) {
+                return;
+            }
+
+            Rect bounds = mTempBounds;
+            info.getBoundsInParent(bounds);
+            bounds.scale(scale);
+            info.setBoundsInParent(bounds);
+
+            info.getBoundsInScreen(bounds);
+            bounds.scale(scale);
+            info.setBoundsInScreen(bounds);
+        }
     }
 
     final class SecurityPolicy {
@@ -1107,7 +1151,9 @@
             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_SELECTED
-            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
+            | AccessibilityEvent.TYPE_VIEW_SCROLLED;
 
         private int mRetrievalAlowingWindowId;
 
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index aab189a6..1af7015 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -26,7 +26,6 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
@@ -73,15 +72,6 @@
     private static final int STATE_DRAGGING = 0x00000002;
     private static final int STATE_DELEGATING = 0x00000004;
 
-    // Human readable symbolic names for the states of the explorer.
-    private static final SparseArray<String> sStateSymbolicNames = new SparseArray<String>();
-    static {
-        SparseArray<String> symbolicNames = sStateSymbolicNames;
-        symbolicNames.append(STATE_TOUCH_EXPLORING, "STATE_TOUCH_EXPLORING");
-        symbolicNames.append(STATE_DRAGGING, "STATE_DRAGING");
-        symbolicNames.append(STATE_DELEGATING, "STATE_DELEGATING");
-    }
-
     // Invalid pointer ID.
     private static final int INVALID_POINTER_ID = -1;
 
@@ -189,7 +179,7 @@
         if (DEBUG) {
             Slog.d(LOG_TAG_RECEIVED, "Received event: " + event + ", policyFlags=0x"
                     + Integer.toHexString(policyFlags));
-            Slog.d(LOG_TAG_STATE, sStateSymbolicNames.get(mCurrentState));
+            Slog.d(LOG_TAG_STATE, getStateSymbolicName(mCurrentState));
         }
 
         // Keep track of the pointers's state.
@@ -708,8 +698,7 @@
     private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
         final PointerProperties[] pointerProperties = mTempPointerProperties;
         final PointerCoords[] pointerCoords = mTempPointerCoords;
-        final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
-        final int pointerIndex = prototype.findPointerIndex(pointerId);
+        final int pointerIndex = prototype.getActionIndex();
 
         // Send down.
         prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
@@ -884,6 +873,25 @@
     }
 
     /**
+     * Gets the symbolic name of a state.
+     *
+     * @param state A state.
+     * @return The state symbolic name.
+     */
+    private static String getStateSymbolicName(int state) {
+        switch (state) {
+            case STATE_TOUCH_EXPLORING:
+                return "STATE_TOUCH_EXPLORING";
+            case STATE_DRAGGING:
+                return "STATE_DRAGGING";
+            case STATE_DELEGATING:
+                return "STATE_DELEGATING";
+            default:
+                throw new IllegalArgumentException("Unknown state: " + state);
+        }
+    }
+
+    /**
      * Helper class for tracking pointers and more specifically which of
      * them are currently down, which are active, and which are delivered
      * to the view hierarchy. The enclosing {@link TouchExplorer} uses the
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d8772b8..b94ee58 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -73,7 +73,7 @@
  */
 final class ActivityStack {
     static final String TAG = ActivityManagerService.TAG;
-    static final boolean localLOGV = ActivityManagerService.localLOGV || true;
+    static final boolean localLOGV = ActivityManagerService.localLOGV;
     static final boolean DEBUG_SWITCH = ActivityManagerService.DEBUG_SWITCH;
     static final boolean DEBUG_PAUSE = ActivityManagerService.DEBUG_PAUSE;
     static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY;
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index a769c05..917259a 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -60,12 +60,12 @@
 
         setCancelable(false);
 
-        setButton(DialogInterface.BUTTON_POSITIVE,
+        setButton(DialogInterface.BUTTON_NEGATIVE,
                 res.getText(com.android.internal.R.string.force_close),
                 mHandler.obtainMessage(FORCE_QUIT));
 
         if (app.errorReportReceiver != null) {
-            setButton(DialogInterface.BUTTON_NEGATIVE,
+            setButton(DialogInterface.BUTTON_POSITIVE,
                     res.getText(com.android.internal.R.string.report),
                     mHandler.obtainMessage(FORCE_QUIT_AND_REPORT));
         }
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index b2737dc..b40f87a 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -77,7 +77,7 @@
                 ? res.getString(resid, name1.toString(), name2.toString())
                 : res.getString(resid, name1.toString()));
 
-        setButton(DialogInterface.BUTTON_POSITIVE,
+        setButton(DialogInterface.BUTTON_NEGATIVE,
                 res.getText(com.android.internal.R.string.force_close),
                 mHandler.obtainMessage(FORCE_CLOSE));
         setButton(DialogInterface.BUTTON_NEUTRAL,
@@ -85,7 +85,7 @@
                 mHandler.obtainMessage(WAIT));
 
         if (app.errorReportReceiver != null) {
-            setButton(DialogInterface.BUTTON_NEGATIVE,
+            setButton(DialogInterface.BUTTON_POSITIVE,
                     res.getText(com.android.internal.R.string.report),
                     mHandler.obtainMessage(WAIT_AND_REPORT));
         }
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index b4fdc9f..293702d 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -446,6 +446,15 @@
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
     
+    private void dumpHelp(PrintWriter pw) {
+        pw.println("Battery stats (batteryinfo) dump options:");
+        pw.println("  [--checkin] [--reset] [--write] [-h]");
+        pw.println("  --checkin: format output for a checkin report.");
+        pw.println("  --reset: reset the stats, clearing all current data.");
+        pw.println("  --write: force write current collected stats to disk.");
+        pw.println("  -h: print this help text.");
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         boolean isCheckin = false;
@@ -466,8 +475,12 @@
                         pw.println("Battery stats written.");
                         noOutput = true;
                     }
+                } else if ("-h".equals(arg)) {
+                    dumpHelp(pw);
+                    return;
                 } else {
                     pw.println("Unknown option: " + arg);
+                    dumpHelp(pw);
                 }
             }
         }
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 15e67d0..6bb7949 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -57,7 +57,9 @@
 import java.io.PrintWriter;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Set;
 /**
@@ -82,7 +84,15 @@
     private String[] mTetherableUsbRegexs;
     private String[] mTetherableWifiRegexs;
     private String[] mTetherableBluetoothRegexs;
-    private String[] mUpstreamIfaceRegexs;
+    private Collection<Integer> mUpstreamIfaceTypes;
+
+    private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
+    private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
+    private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
+
+    // if we have to connect to mobile, what APN type should we use?  Calculated by examining the
+    // upstream type list and the DUN_REQUIRED secure-setting
+    private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
 
     private INetworkManagementService mNMService;
     private Looper mLooper;
@@ -112,9 +122,6 @@
     private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
     private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
 
-    // resampled each time we turn on tethering - used as cache for settings/config-val
-    private boolean mDunRequired;  // configuration info - must use DUN apn on 3g
-
     private StateMachine mTetherMasterSM;
 
     private Notification mTetheredNotification;
@@ -159,7 +166,6 @@
         if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
             mDhcpRange = DHCP_DEFAULT_RANGE;
         }
-        mDunRequired = false; // resample when we turn on
 
         mTetherableUsbRegexs = context.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_usb_regexs);
@@ -167,8 +173,15 @@
                 com.android.internal.R.array.config_tether_wifi_regexs);
         mTetherableBluetoothRegexs = context.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_bluetooth_regexs);
-        mUpstreamIfaceRegexs = context.getResources().getStringArray(
-                com.android.internal.R.array.config_tether_upstream_regexs);
+        int ifaceTypes[] = context.getResources().getIntArray(
+                com.android.internal.R.array.config_tether_upstream_types);
+        mUpstreamIfaceTypes = new ArrayList();
+        for (int i : ifaceTypes) {
+            mUpstreamIfaceTypes.add(new Integer(i));
+        }
+
+        // check if the upstream type list needs to be modified due to secure-settings
+        checkDunRequired();
 
         // TODO - remove and rely on real notifications of the current iface
         mDnsServers = new String[2];
@@ -176,8 +189,8 @@
         mDnsServers[1] = DNS_DEFAULT_SERVER2;
     }
 
-    public void interfaceLinkStatusChanged(String iface, boolean link) {
-        if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
+    public void interfaceStatusChanged(String iface, boolean up) {
+        if (DEBUG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
         boolean found = false;
         boolean usb = false;
         if (isWifi(iface)) {
@@ -192,7 +205,7 @@
 
         synchronized (mIfaces) {
             TetherInterfaceSM sm = mIfaces.get(iface);
-            if (link) {
+            if (up) {
                 if (sm == null) {
                     sm = new TetherInterfaceSM(iface, mLooper, usb);
                     mIfaces.put(iface, sm);
@@ -207,6 +220,11 @@
         }
     }
 
+    public void interfaceLinkStateChanged(String iface, boolean up) {
+        if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
+        interfaceStatusChanged(iface, up);
+    }
+
     private boolean isUsb(String iface) {
         for (String regex : mTetherableUsbRegexs) {
             if (iface.matches(regex)) return true;
@@ -509,9 +527,9 @@
         }
         try {
             if (enabled) {
-                usbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_RNDIS);
+                usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
             } else {
-                usbManager.setPrimaryFunction(null);
+                usbManager.setCurrentFunction(null, false);
             }
         } catch (Exception e) {
             Log.e(TAG, "Error toggling usb RNDIS", e);
@@ -582,16 +600,44 @@
         return mTetherableBluetoothRegexs;
     }
 
-    public String[] getUpstreamIfaceRegexs() {
-        return mUpstreamIfaceRegexs;
+    public int[] getUpstreamIfaceTypes() {
+        int values[] = new int[mUpstreamIfaceTypes.size()];
+        Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
+        for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
+            values[i] = iterator.next();
+        }
+        return values;
     }
 
-    public boolean isDunRequired() {
-        boolean defaultVal = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_tether_dun_required);
-        boolean result = (Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1);
-        return result;
+    public void checkDunRequired() {
+        int requiredApn = ((Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.TETHER_DUN_REQUIRED, 0) == 1) ?
+                ConnectivityManager.TYPE_MOBILE_DUN :
+                ConnectivityManager.TYPE_MOBILE_HIPRI);
+        if (mPreferredUpstreamMobileApn != requiredApn) {
+            if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
+                while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
+                    mUpstreamIfaceTypes.remove(MOBILE_TYPE);
+                }
+                while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
+                    mUpstreamIfaceTypes.remove(HIPRI_TYPE);
+                }
+                if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
+                    mUpstreamIfaceTypes.add(DUN_TYPE);
+                }
+            } else {
+                while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
+                    mUpstreamIfaceTypes.remove(DUN_TYPE);
+                }
+                if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
+                    mUpstreamIfaceTypes.add(MOBILE_TYPE);
+                }
+                if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
+                    mUpstreamIfaceTypes.add(HIPRI_TYPE);
+                }
+            }
+            mPreferredUpstreamMobileApn = requiredApn;
+        }
     }
 
     public String[] getTetheredIfaces() {
@@ -648,15 +694,12 @@
         return retVal;
     }
 
-    public void handleTetherIfaceChange(String iface) {
-        // check if iface is white listed
-        for (String regex : mUpstreamIfaceRegexs) {
-            if (iface.matches(regex)) {
-                if (DEBUG) Log.d(TAG, "Tethering got Interface Change");
-                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_IFACE_CHANGED, iface);
-                break;
-            }
-        }
+    //TODO: Temporary handling upstream change triggered without
+    //      CONNECTIVITY_ACTION. Only to accomodate interface
+    //      switch during HO.
+    //      @see bug/4455071
+    public void handleTetherIfaceChange() {
+        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
     }
 
     class TetherInterfaceSM extends StateMachine {
@@ -1051,8 +1094,6 @@
         static final int CMD_CELL_CONNECTION_RENEW   = 4;
         // we don't have a valid upstream conn, check again after a delay
         static final int CMD_RETRY_UPSTREAM          = 5;
-        // received an indication that upstream interface has changed
-        static final int CMD_IFACE_CHANGED           = 6;
 
         // This indicates what a timeout event relates to.  A state that
         // sends itself a delayed timeout event and handles incoming timeout events
@@ -1072,7 +1113,7 @@
         private ArrayList mNotifyList;
 
         private int mCurrentConnectionSequence;
-        private boolean mMobileReserved = false;
+        private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
 
         private String mUpstreamIfaceName = null;
 
@@ -1111,22 +1152,34 @@
             public boolean processMessage(Message m) {
                 return false;
             }
-            protected boolean turnOnMobileConnection() {
+            protected String enableString(int apnType) {
+                switch (apnType) {
+                case ConnectivityManager.TYPE_MOBILE_DUN:
+                    return Phone.FEATURE_ENABLE_DUN_ALWAYS;
+                case ConnectivityManager.TYPE_MOBILE:
+                case ConnectivityManager.TYPE_MOBILE_HIPRI:
+                    return Phone.FEATURE_ENABLE_HIPRI;
+                }
+                return null;
+            }
+            protected boolean turnOnUpstreamMobileConnection(int apnType) {
                 boolean retValue = true;
-                if (mMobileReserved) return retValue;
+                if (apnType == ConnectivityManager.TYPE_NONE) return false;
+                if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                 int result = Phone.APN_REQUEST_FAILED;
+                String enableString = enableString(apnType);
+                if (enableString == null) return false;
                 try {
                     result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
-                            (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS :
-                            Phone.FEATURE_ENABLE_HIPRI), new Binder());
+                            enableString, new Binder());
                 } catch (Exception e) {
                 }
                 switch (result) {
                 case Phone.APN_ALREADY_ACTIVE:
                 case Phone.APN_REQUEST_STARTED:
-                    mMobileReserved = true;
+                    mMobileApnReserved = apnType;
                     Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
                     m.arg1 = ++mCurrentConnectionSequence;
                     sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
@@ -1139,18 +1192,17 @@
 
                 return retValue;
             }
-            protected boolean turnOffMobileConnection() {
-                if (mMobileReserved) {
+            protected boolean turnOffUpstreamMobileConnection() {
+                if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
                     IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                     IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                     try {
                         cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
-                                (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS :
-                                             Phone.FEATURE_ENABLE_HIPRI));
+                                enableString(mMobileApnReserved));
                     } catch (Exception e) {
                         return false;
                     }
-                    mMobileReserved = false;
+                    mMobileApnReserved = ConnectivityManager.TYPE_NONE;
                 }
                 return true;
             }
@@ -1196,108 +1248,55 @@
                 transitionTo(mInitialState);
                 return true;
             }
-            protected String findActiveUpstreamIface() {
-                // check for what iface we can use - if none found switch to error.
-                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
-
-                try {
-                    LinkProperties defaultProp = cm.getActiveLinkProperties();
-                    if (defaultProp != null) {
-                        String iface = defaultProp.getInterfaceName();
-                        for(String regex : mUpstreamIfaceRegexs) {
-                            if (iface.matches(regex)) return iface;
-                        }
-                    }
-                } catch (RemoteException e) { }
-
-                String[] ifaces = new String[0];
-                try {
-                    ifaces = mNMService.listInterfaces();
-                } catch (Exception e) {
-                    Log.e(TAG, "Error listing Interfaces", e);
-                    return null;
-                }
-
-                for (String regex : mUpstreamIfaceRegexs) {
-                    for (String iface : ifaces) {
-                        if (iface.matches(regex)) {
-                            // verify it is active
-                            InterfaceConfiguration ifcg = null;
-                            try {
-                                ifcg = mNMService.getInterfaceConfig(iface);
-                                if (ifcg.isActive()) {
-                                    return iface;
-                                }
-                            } catch (Exception e) {
-                                Log.e(TAG, "Error getting iface config", e);
-                                // ignore - try next
-                                continue;
-                            }
-                        }
-                    }
-                }
-                return null;
-            }
 
             protected void chooseUpstreamType(boolean tryCell) {
-                // decide if the current upstream is good or not and if not
-                // do something about it (start up DUN if required or HiPri if not)
-                String iface = findActiveUpstreamIface();
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
-                mMobileReserved = false;
-                if (DEBUG) {
-                    Log.d(TAG, "chooseUpstreamType(" + tryCell + "),  dunRequired ="
-                            + mDunRequired + ", iface=" + iface);
-                }
-                if (iface != null) {
+                int upType = ConnectivityManager.TYPE_NONE;
+                String iface = null;
+
+                for (Integer netType : mUpstreamIfaceTypes) {
+                    NetworkInfo info = null;
                     try {
-                        if (mDunRequired) {
-                            // check if Dun is on - we can use that
-                            NetworkInfo info = cm.getNetworkInfo(
-                                    ConnectivityManager.TYPE_MOBILE_DUN);
-                            if (info.isConnected()) {
-                                if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface);
-                                // even if we're already connected - it may be somebody else's
-                                // refcount, so add our own
-                                turnOnMobileConnection();
-                            } else {
-                                // verify the iface is not the default mobile - can't use that!
-                                info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-                                if (info.isConnected()) {
-                                    iface = null; // can't accept this one
-                                }
-                            }
-                        } else {
-                            if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection");
-                            NetworkInfo info = cm.getNetworkInfo(
-                                    ConnectivityManager.TYPE_MOBILE_HIPRI);
-                            if (info.isConnected()) {
-                                if (DEBUG) Log.d(TAG, "yes - hipri in use");
-                                // even if we're already connected - it may be sombody else's
-                                // refcount, so add our own
-                                turnOnMobileConnection();
-                            }
-                        }
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "RemoteException calling ConnectivityManager", e);
-                        iface = null;
+                        info = cm.getNetworkInfo(netType.intValue());
+                    } catch (RemoteException e) { }
+                    if ((info != null) && info.isConnected()) {
+                        upType = netType.intValue();
+                        break;
                     }
                 }
-                // may have been set to null in the if above
-                if (iface == null ) {
-                    boolean success = false;
-                    if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
-                        success = turnOnMobileConnection();
+
+                if (DEBUG) {
+                    Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
+                            + mPreferredUpstreamMobileApn + ", got type=" + upType);
+                }
+
+                // if we're on DUN, put our own grab on it
+                if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
+                        upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
+                    turnOnUpstreamMobileConnection(upType);
+                }
+
+                if (upType == ConnectivityManager.TYPE_NONE) {
+                    boolean tryAgainLater = true;
+                    if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
+                            (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
+                        // we think mobile should be coming up - don't set a retry
+                        tryAgainLater = false;
                     }
-                    if (!success) {
-                        // wait for things to settle and retry
+                    if (tryAgainLater) {
                         sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
                     }
+                } else {
+                    LinkProperties linkProperties = null;
+                    try {
+                        linkProperties = cm.getLinkProperties(upType);
+                    } catch (RemoteException e) { }
+                    if (linkProperties != null) iface = linkProperties.getInterfaceName();
                 }
                 notifyTetheredOfNewUpstreamIface(iface);
             }
+
             protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
                 if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
                 mUpstreamIfaceName = ifaceName;
@@ -1312,7 +1311,6 @@
         class InitialState extends TetherMasterUtilState {
             @Override
             public void enter() {
-                mMobileReserved = false;
             }
             @Override
             public boolean processMessage(Message message) {
@@ -1320,7 +1318,7 @@
                 boolean retValue = true;
                 switch (message.what) {
                     case CMD_TETHER_MODE_REQUESTED:
-                        mDunRequired = isDunRequired();
+                        checkDunRequired();
                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
                         if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString());
                         mNotifyList.add(who);
@@ -1354,7 +1352,7 @@
             }
             @Override
             public void exit() {
-                turnOffMobileConnection();
+                turnOffUpstreamMobileConnection();
                 notifyTetheredOfNewUpstreamIface(null);
             }
             @Override
@@ -1392,19 +1390,13 @@
                                 Log.d(TAG, "renewing mobile connection - requeuing for another " +
                                         CELL_CONNECTION_RENEW_MS + "ms");
                             }
-                            mMobileReserved = false; // need to renew it
-                            turnOnMobileConnection();
+                            turnOnUpstreamMobileConnection(mMobileApnReserved);
                         }
                         break;
                     case CMD_RETRY_UPSTREAM:
                         chooseUpstreamType(mTryCell);
                         mTryCell = !mTryCell;
                         break;
-                    case CMD_IFACE_CHANGED:
-                        String iface = (String)message.obj;
-                        if (DEBUG) Log.d(TAG, "Activie upstream interface changed: " + iface);
-                        notifyTetheredOfNewUpstreamIface(iface);
-                        break;
                     default:
                         retValue = false;
                         break;
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 47813f8..f5efda9 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -27,15 +27,23 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.net.INetworkManagementEventObserver;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import com.android.internal.R;
 import com.android.internal.net.VpnConfig;
 import com.android.server.ConnectivityService.VpnCallback;
 
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charsets;
+
 /**
  * @hide
  */
@@ -49,7 +57,8 @@
 
     private String mPackageName;
     private String mInterfaceName;
-    private String mDnsPropertyPrefix;
+
+    private LegacyVpnRunner mLegacyVpnRunner;
 
     public Vpn(Context context, VpnCallback callback) {
         mContext = context;
@@ -173,7 +182,11 @@
     }
 
     // INetworkManagementEventObserver.Stub
-    public void interfaceLinkStatusChanged(String name, boolean up) {
+    public void interfaceStatusChanged(String name, boolean up) {
+    }
+
+    // INetworkManagementEventObserver.Stub
+    public void interfaceLinkStateChanged(String name, boolean up) {
     }
 
     // INetworkManagementEventObserver.Stub
@@ -245,4 +258,195 @@
     private native void nativeReset(String name);
     private native int nativeCheck(String name);
     private native void nativeProtect(int fd, String name);
+
+    /**
+     * Handle legacy VPN requests. This method stops the services and restart
+     * them if their arguments are not null. Heavy things are offloaded to
+     * another thread, so callers will not be blocked too long.
+     *
+     * @param raoocn The arguments to be passed to racoon.
+     * @param mtpd The arguments to be passed to mtpd.
+     */
+    public synchronized void doLegacyVpn(String[] racoon, String[] mtpd) {
+        // Currently only system user is allowed.
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Unauthorized Caller");
+        }
+
+        // If the previous runner is still alive, interrupt it.
+        if (mLegacyVpnRunner != null && mLegacyVpnRunner.isAlive()) {
+            mLegacyVpnRunner.interrupt();
+        }
+
+        // Start a new runner and we are done!
+        mLegacyVpnRunner = new LegacyVpnRunner(
+                new String[] {"racoon", "mtpd"}, racoon, mtpd);
+        mLegacyVpnRunner.start();
+    }
+
+    /**
+     * Bringing up a VPN connection takes time, and that is all this thread
+     * does. Here we have plenty of time. The only thing we need to take
+     * care of is responding to interruptions as soon as possible. Otherwise
+     * requests will be piled up. This can be done in a Handler as a state
+     * machine, but it is much easier to read in the current form.
+     */
+    private class LegacyVpnRunner extends Thread {
+        private static final String TAG = "LegacyVpnRunner";
+
+        private static final String NONE = "--";
+
+        private final String[] mServices;
+        private final String[][] mArguments;
+        private long mTimer = -1;
+
+        public LegacyVpnRunner(String[] services, String[]... arguments) {
+            super(TAG);
+            mServices = services;
+            mArguments = arguments;
+        }
+
+        @Override
+        public void run() {
+            // Wait for the previous thread since it has been interrupted.
+            Log.v(TAG, "wait");
+            synchronized (TAG) {
+                Log.v(TAG, "run");
+                execute();
+                Log.v(TAG, "exit");
+            }
+        }
+
+        private void checkpoint(boolean yield) throws InterruptedException {
+            long now = SystemClock.elapsedRealtime();
+            if (mTimer == -1) {
+                mTimer = now;
+                Thread.sleep(1);
+            } else if (now - mTimer <= 30000) {
+                Thread.sleep(yield ? 200 : 1);
+            } else {
+                throw new InterruptedException("timeout");
+            }
+        }
+
+        private void execute() {
+            // Catch all exceptions so we can clean up few things.
+            try {
+                // Initialize the timer.
+                checkpoint(false);
+
+                // First stop the services.
+                for (String service : mServices) {
+                    SystemProperties.set("ctl.stop", service);
+                }
+
+                // Wait for the services to stop.
+                for (String service : mServices) {
+                    String key = "init.svc." + service;
+                    while (!"stopped".equals(SystemProperties.get(key))) {
+                        checkpoint(true);
+                    }
+                }
+
+                // Reset the properties.
+                SystemProperties.set("vpn.dns", NONE);
+                SystemProperties.set("vpn.via", NONE);
+                while (!NONE.equals(SystemProperties.get("vpn.dns")) ||
+                        !NONE.equals(SystemProperties.get("vpn.via"))) {
+                    checkpoint(true);
+                }
+
+                // Check if we need to restart some services.
+                boolean restart = false;
+                for (String[] arguments : mArguments) {
+                    restart = restart || (arguments != null);
+                }
+                if (!restart) {
+                    return;
+                }
+
+                // Start the service with arguments.
+                for (int i = 0; i < mServices.length; ++i) {
+                    String[] arguments = mArguments[i];
+                    if (arguments == null) {
+                        continue;
+                    }
+
+                    // Start the service.
+                    String service = mServices[i];
+                    SystemProperties.set("ctl.start", service);
+
+                    // Wait for the service to start.
+                    String key = "init.svc." + service;
+                    while (!"running".equals(SystemProperties.get(key))) {
+                        checkpoint(true);
+                    }
+
+                    // Create the control socket.
+                    LocalSocket socket = new LocalSocket();
+                    LocalSocketAddress address = new LocalSocketAddress(
+                            service, LocalSocketAddress.Namespace.RESERVED);
+
+                    // Wait for the socket to connect.
+                    while (true) {
+                        try {
+                            socket.connect(address);
+                            break;
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                        checkpoint(true);
+                    }
+                    socket.setSoTimeout(500);
+
+                    // Send over the arguments.
+                    OutputStream output = socket.getOutputStream();
+                    for (String argument : arguments) {
+                        byte[] bytes = argument.getBytes(Charsets.UTF_8);
+                        if (bytes.length >= 0xFFFF) {
+                            throw new IllegalArgumentException("argument too large");
+                        }
+                        output.write(bytes.length >> 8);
+                        output.write(bytes.length);
+                        output.write(bytes);
+                        checkpoint(false);
+                    }
+
+                    // Send End-Of-Arguments.
+                    output.write(0xFF);
+                    output.write(0xFF);
+                    output.flush();
+                    socket.close();
+                }
+
+                // Now here is the beast from the old days. We check few
+                // properties to figure out the current status. Ideally we
+                // can read things back from the sockets and get rid of the
+                // properties, but we have no time...
+                while (NONE.equals(SystemProperties.get("vpn.dns")) ||
+                        NONE.equals(SystemProperties.get("vpn.via"))) {
+
+                    // Check if a running service is dead.
+                    for (int i = 0; i < mServices.length; ++i) {
+                        String service = mServices[i];
+                        if (mArguments[i] != null && !"running".equals(
+                                SystemProperties.get("init.svc." + service))) {
+                            throw new IllegalArgumentException(service + " is dead");
+                        }
+                    }
+                    checkpoint(true);
+                }
+
+                // Great! Now we are connected!
+                Log.i(TAG, "connected!");
+                // TODO:
+
+            } catch (Exception e) {
+                Log.i(TAG, e.getMessage());
+                for (String service : mServices) {
+                    SystemProperties.set("ctl.stop", service);
+                }
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 67e73f5f..4fa3bda 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -132,7 +132,7 @@
     private static final int GPS_CAPABILITY_MSB = 0x0000002;
     private static final int GPS_CAPABILITY_MSA = 0x0000004;
     private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
-
+    private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
 
     // these need to match AGpsType enum in gps.h
     private static final int AGPS_TYPE_SUPL = 1;
@@ -200,6 +200,9 @@
     private boolean mInjectNtpTimePending = true;
     private boolean mDownloadXtraDataPending = true;
 
+    // set to true if the GPS engine does not do on-demand NTP time requests
+    private boolean mPeriodicTimeInjection;
+
     // true if GPS is navigating
     private boolean mNavigating;
 
@@ -549,10 +552,12 @@
             delay = RETRY_INTERVAL;
         }
 
-        // send delayed message for next NTP injection
-        // since this is delayed and not urgent we do not hold a wake lock here
-        mHandler.removeMessages(INJECT_NTP_TIME);
-        mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+        if (mPeriodicTimeInjection) {
+            // send delayed message for next NTP injection
+            // since this is delayed and not urgent we do not hold a wake lock here
+            mHandler.removeMessages(INJECT_NTP_TIME);
+            mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+        }
     }
 
     private void handleDownloadXtraData() {
@@ -1305,6 +1310,11 @@
      */
     private void setEngineCapabilities(int capabilities) {
         mEngineCapabilities = capabilities;
+
+        if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
+            mPeriodicTimeInjection = true;
+            requestUtcTime();
+        }
     }
 
     /**
@@ -1438,6 +1448,14 @@
     }
 
     /**
+     * Called from native code to request utc time info
+     */
+
+    private void requestUtcTime() {
+        sendMessage(INJECT_NTP_TIME, 0, null);
+    }
+
+    /**
      * Called from native code to request reference location info
      */
 
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 584cd03..1f2ec2c 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -25,6 +25,7 @@
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.*;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -57,6 +58,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
@@ -71,7 +74,9 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.INetworkManagementService;
 import android.os.IPowerManager;
+import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.telephony.TelephonyManager;
@@ -108,6 +113,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 
 import libcore.io.IoUtils;
 
@@ -148,10 +154,14 @@
 
     private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
 
+    private static final int MSG_RULES_CHANGED = 0x1;
+    private static final int MSG_METERED_IFACES_CHANGED = 0x2;
+
     private final Context mContext;
     private final IActivityManager mActivityManager;
     private final IPowerManager mPowerManager;
     private final INetworkStatsService mNetworkStats;
+    private final INetworkManagementService mNetworkManagement;
     private final TrustedTime mTime;
 
     private IConnectivityManager mConnManager;
@@ -160,6 +170,7 @@
     private final Object mRulesLock = new Object();
 
     private boolean mScreenOn;
+    private boolean mBackgroundData;
 
     /** Current policy for network templates. */
     private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList();
@@ -188,11 +199,14 @@
     // TODO: keep whitelist of system-critical services that should never have
     // rules enforced, such as system, phone, and radio UIDs.
 
+    // TODO: watch for package added broadcast to catch new UIDs.
+
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
-            IPowerManager powerManager, INetworkStatsService networkStats) {
+            IPowerManager powerManager, INetworkStatsService networkStats,
+            INetworkManagementService networkManagement) {
         // TODO: move to using cached NtpTrustedTime
-        this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(),
-                getSystemDir());
+        this(context, activityManager, powerManager, networkStats, networkManagement,
+                new NtpTrustedTime(), getSystemDir());
     }
 
     private static File getSystemDir() {
@@ -200,17 +214,19 @@
     }
 
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
-            IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time,
-            File systemDir) {
+            IPowerManager powerManager, INetworkStatsService networkStats,
+            INetworkManagementService networkManagement,
+            TrustedTime time, File systemDir) {
         mContext = checkNotNull(context, "missing context");
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
         mPowerManager = checkNotNull(powerManager, "missing powerManager");
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
+        mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement");
         mTime = checkNotNull(time, "missing TrustedTime");
 
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
+        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
 
         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
     }
@@ -231,6 +247,7 @@
         }
 
         updateScreenOn();
+        updateBackgroundData(true);
 
         try {
             mActivityManager.registerProcessObserver(mProcessObserver);
@@ -256,11 +273,15 @@
         final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
         mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
 
-        // listen for warning polling events; currently dispatched by
+        // listen for stats update events
         final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
         mContext.registerReceiver(
                 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
 
+        // listen for changes to background data flag
+        final IntentFilter bgFilter = new IntentFilter(ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+        mContext.registerReceiver(mBgReceiver, bgFilter, CONNECTIVITY_INTERNAL, mHandler);
+
     }
 
     private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
@@ -269,9 +290,6 @@
             // only someone like AMS should only be calling us
             mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
 
-            // skip when UID couldn't have any policy
-            if (!isUidValidForPolicy(mContext, uid)) return;
-
             synchronized (mRulesLock) {
                 // because a uid can have multiple pids running inside, we need to
                 // remember all pid states and summarize foreground at uid level.
@@ -292,9 +310,6 @@
             // only someone like AMS should only be calling us
             mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
 
-            // skip when UID couldn't have any policy
-            if (!isUidValidForPolicy(mContext, uid)) return;
-
             synchronized (mRulesLock) {
                 // clear records and recompute, when they exist
                 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
@@ -349,6 +364,22 @@
     };
 
     /**
+     * Receiver that watches for
+     * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
+     */
+    private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // on background handler thread, and verified CONNECTIVITY_INTERNAL
+            // permission above.
+
+            synchronized (mRulesLock) {
+                updateBackgroundData(false);
+            }
+        }
+    };
+
+    /**
      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
      * to show visible notifications as needed.
      */
@@ -561,7 +592,7 @@
         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
                 : System.currentTimeMillis();
 
-        mMeteredIfaces.clear();
+        final HashSet<String> newMeteredIfaces = Sets.newHashSet();
 
         // apply each policy that we found ifaces for; compute remaining data
         // based on current cycle and historical stats, and push to kernel.
@@ -591,28 +622,30 @@
             if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
                 // remaining "quota" is based on usage in current cycle
                 final long quota = Math.max(0, policy.limitBytes - total);
-                //kernelSetIfacesQuota(ifaces, quota);
+
+                if (ifaces.length > 1) {
+                    // TODO: switch to shared quota once NMS supports
+                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
+                }
 
                 for (String iface : ifaces) {
-                    mMeteredIfaces.add(iface);
+                    removeInterfaceQuota(iface);
+                    setInterfaceQuota(iface, quota);
+                    newMeteredIfaces.add(iface);
                 }
             }
         }
 
-        // dispatch changed rule to existing listeners
-        // TODO: dispatch outside of holding lock
-        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
-        final int length = mListeners.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-            if (listener != null) {
-                try {
-                    listener.onMeteredIfacesChanged(meteredIfaces);
-                } catch (RemoteException e) {
-                }
+        // remove quota on any trailing interfaces
+        for (String iface : mMeteredIfaces) {
+            if (!newMeteredIfaces.contains(iface)) {
+                removeInterfaceQuota(iface);
             }
         }
-        mListeners.finishBroadcast();
+        mMeteredIfaces = newMeteredIfaces;
+
+        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
+        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
     }
 
     /**
@@ -804,32 +837,7 @@
 
         mListeners.register(listener);
 
-        synchronized (mRulesLock) {
-            // dispatch any existing rules to new listeners
-            // TODO: dispatch outside of holding lock
-            final int size = mUidRules.size();
-            for (int i = 0; i < size; i++) {
-                final int uid = mUidRules.keyAt(i);
-                final int uidRules = mUidRules.valueAt(i);
-                if (uidRules != RULE_ALLOW_ALL) {
-                    try {
-                        listener.onUidRulesChanged(uid, uidRules);
-                    } catch (RemoteException e) {
-                    }
-                }
-            }
-
-            // dispatch any metered ifaces to new listeners
-            // TODO: dispatch outside of holding lock
-            if (mMeteredIfaces.size() > 0) {
-                final String[] meteredIfaces = mMeteredIfaces.toArray(
-                        new String[mMeteredIfaces.size()]);
-                try {
-                    listener.onMeteredIfacesChanged(meteredIfaces);
-                } catch (RemoteException e) {
-                }
-            }
-        }
+        // TODO: consider dispatching existing rules to new listeners
     }
 
     @Override
@@ -963,6 +971,21 @@
         }
     }
 
+    private void updateBackgroundData(boolean systemReady) {
+        synchronized (mRulesLock) {
+            try {
+                mBackgroundData = mConnManager.getBackgroundDataSetting();
+            } catch (RemoteException e) {
+            }
+            if (systemReady && mBackgroundData) {
+                // typical behavior of background enabled during systemReady;
+                // no need to clear rules for all UIDs.
+            } else {
+                updateRulesForBackgroundDataLocked();
+            }
+        }
+    }
+
     /**
      * Update rules that might be changed by {@link #mScreenOn} value.
      */
@@ -977,9 +1000,34 @@
         }
     }
 
-    private void updateRulesForUidLocked(int uid) {
-        if (!isUidValidForPolicy(mContext, uid)) return;
+    /**
+     * Update rules that might be changed by {@link #mBackgroundData} value.
+     */
+    private void updateRulesForBackgroundDataLocked() {
+        // update rules for all installed applications
+        final PackageManager pm = mContext.getPackageManager();
+        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
+        for (ApplicationInfo app : apps) {
+            updateRulesForUidLocked(app.uid);
+        }
 
+        // and catch system UIDs
+        // TODO: keep in sync with android_filesystem_config.h
+        for (int uid = 1000; uid <= 1025; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+        for (int uid = 2000; uid <= 2002; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+        for (int uid = 3000; uid <= 3007; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+        for (int uid = 9998; uid <= 9999; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+    }
+
+    private void updateRulesForUidLocked(int uid) {
         final int uidPolicy = getUidPolicy(uid);
         final boolean uidForeground = isUidForeground(uid);
 
@@ -989,6 +1037,10 @@
             // uid in background, and policy says to block metered data
             uidRules = RULE_REJECT_METERED;
         }
+        if (!uidForeground && !mBackgroundData) {
+            // uid in background, and global background disabled
+            uidRules = RULE_REJECT_METERED;
+        }
 
         // TODO: only dispatch when rules actually change
 
@@ -996,21 +1048,82 @@
         mUidRules.put(uid, uidRules);
 
         final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
-        //kernelSetUidRejectPaid(uid, rejectPaid);
+        setUidNetworkRules(uid, rejectMetered);
 
         // dispatch changed rule to existing listeners
-        // TODO: dispatch outside of holding lock
-        final int length = mListeners.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-            if (listener != null) {
-                try {
-                    listener.onUidRulesChanged(uid, uidRules);
-                } catch (RemoteException e) {
+        mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
+    }
+
+    private Handler.Callback mHandlerCallback = new Handler.Callback() {
+        /** {@inheritDoc} */
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_RULES_CHANGED: {
+                    final int uid = msg.arg1;
+                    final int uidRules = msg.arg2;
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        if (listener != null) {
+                            try {
+                                listener.onUidRulesChanged(uid, uidRules);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                    }
+                    mListeners.finishBroadcast();
+                    return true;
+                }
+                case MSG_METERED_IFACES_CHANGED: {
+                    final String[] meteredIfaces = (String[]) msg.obj;
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        if (listener != null) {
+                            try {
+                                listener.onMeteredIfacesChanged(meteredIfaces);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                    }
+                    mListeners.finishBroadcast();
+                    return true;
+                }
+                default: {
+                    return false;
                 }
             }
         }
-        mListeners.finishBroadcast();
+    };
+
+    private void setInterfaceQuota(String iface, long quota) {
+        try {
+            mNetworkManagement.setInterfaceQuota(iface, quota);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem setting interface quota", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem setting interface quota", e);
+        }
+    }
+
+    private void removeInterfaceQuota(String iface) {
+        try {
+            mNetworkManagement.removeInterfaceQuota(iface);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem removing interface quota", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem removing interface quota", e);
+        }
+    }
+
+    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+        try {
+            mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem setting uid rules", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem setting uid rules", e);
+        }
     }
 
     private String getActiveSubscriberId() {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 043a581..7610a11 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -27,6 +27,7 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_REMOVED;
+import static android.provider.Settings.Secure.NETSTATS_ENABLED;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
 import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
@@ -70,6 +71,7 @@
 import android.util.TrustedTime;
 
 import com.android.internal.os.AtomicFile;
+import com.android.server.NativeDaemonConnectorException;
 import com.google.android.collect.Maps;
 import com.google.android.collect.Sets;
 
@@ -122,8 +124,6 @@
     private PendingIntent mPollIntent;
 
     // TODO: listen for kernel push events through netd instead of polling
-    // TODO: watch for UID uninstall, and transfer stats into single bucket
-
     // TODO: trim empty history objects entirely
 
     private static final long KB_IN_BYTES = 1024;
@@ -134,6 +134,7 @@
      * Settings that can be changed externally.
      */
     public interface NetworkStatsSettings {
+        public boolean getEnabled();
         public long getPollInterval();
         public long getPersistThreshold();
         public long getNetworkBucketDuration();
@@ -206,6 +207,20 @@
     }
 
     public void systemReady() {
+        if (mSettings.getEnabled()) {
+            try {
+                // enable low-level bandwidth stats and control
+                // TODO: consider shipping with this enabled by default
+                mNetworkManager.setBandwidthControlEnabled(true);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "problem talking to netd while enabling bandwidth controls", e);
+            } catch (NativeDaemonConnectorException ndce) {
+                Slog.e(TAG, "problem enabling bandwidth controls", ndce);
+            }
+        } else {
+            Slog.w(TAG, "detailed network stats disabled");
+        }
+
         synchronized (mStatsLock) {
             // read historical network stats from disk, since policy service
             // might need them right away. we delay loading detailed UID stats
@@ -489,8 +504,11 @@
         try {
             networkSnapshot = mNetworkManager.getNetworkStatsSummary();
             uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
+        } catch (IllegalStateException e) {
+            Slog.w(TAG, "problem reading network stats: " + e);
+            return;
         } catch (RemoteException e) {
-            Slog.w(TAG, "problem reading network stats");
+            Slog.w(TAG, "problem reading network stats: " + e);
             return;
         }
 
@@ -1040,6 +1058,15 @@
             return Settings.Secure.getLong(mResolver, name, def);
         }
 
+        public boolean getEnabled() {
+            if (!new File("/proc/net/xt_qtaguid/ctrl").exists()) {
+                Slog.w(TAG, "kernel does not support bandwidth control");
+                return false;
+            }
+            // TODO: once things stabilize, enable by default.
+            // For now: ./vendor/google/tools/override-gservices secure:netstats_enabled=1
+            return Settings.Secure.getInt(mResolver, NETSTATS_ENABLED, 0) != 0;
+        }
         public long getPollInterval() {
             return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS);
         }
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index d10aa97..11ccd60 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -307,7 +307,7 @@
     }
 
     public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
-            PackageStats pStats) {
+            String asecPath, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
@@ -315,17 +315,20 @@
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
+        builder.append(' ');
+        builder.append(asecPath != null ? asecPath : "!");
 
         String s = transaction(builder.toString());
         String res[] = s.split(" ");
 
-        if ((res == null) || (res.length != 4)) {
+        if ((res == null) || (res.length != 5)) {
             return -1;
         }
         try {
             pStats.codeSize = Long.parseLong(res[1]);
             pStats.dataSize = Long.parseLong(res[2]);
             pStats.cacheSize = Long.parseLong(res[3]);
+            pStats.externalCodeSize = Long.parseLong(res[4]);
             return Integer.parseInt(res[0]);
         } catch (NumberFormatException e) {
             return -1;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 5a9dae9..22e2dde 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -75,6 +75,7 @@
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.FileUtils;
+import android.os.FileUtils.FileStatus;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -4887,8 +4888,7 @@
 
         private final IPackageStatsObserver mObserver;
 
-        public MeasureParams(PackageStats stats, boolean success,
-                IPackageStatsObserver observer) {
+        public MeasureParams(PackageStats stats, boolean success, IPackageStatsObserver observer) {
             mObserver = observer;
             mStats = stats;
             mSuccess = success;
@@ -5480,6 +5480,17 @@
         }
     }
 
+    /**
+     * Extract the MountService "container ID" from the full code path of an
+     * .apk.
+     */
+    static String cidFromCodePath(String fullCodePath) {
+        int eidx = fullCodePath.lastIndexOf("/");
+        String subStr1 = fullCodePath.substring(0, eidx);
+        int sidx = subStr1.lastIndexOf("/");
+        return subStr1.substring(sidx+1, eidx);
+    }
+
     class SdInstallArgs extends InstallArgs {
         static final String RES_FILE_NAME = "pkg.apk";
 
@@ -6831,6 +6842,7 @@
         }
         PackageParser.Package p;
         boolean dataOnly = false;
+        String asecPath = null;
         synchronized (mPackages) {
             p = mPackages.get(packageName);
             if(p == null) {
@@ -6842,6 +6854,12 @@
                 }
                 p = ps.pkg;
             }
+            if (p != null && isExternal(p)) {
+                String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
+                if (secureContainerId != null) {
+                    asecPath = PackageHelper.getSdFilesystem(secureContainerId);
+                }
+            }
         }
         String publicSrcDir = null;
         if(!dataOnly) {
@@ -6850,10 +6868,13 @@
                 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
                 return false;
             }
-            publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
+            if (isForwardLocked(p)) {
+                publicSrcDir = applicationInfo.publicSourceDir;
+            }
         }
         if (mInstaller != null) {
-            int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
+            int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+                    asecPath, pStats);
             if (res < 0) {
                 return false;
             } else {
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index b7f9d5c..918f1b6 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -77,9 +77,8 @@
 
     private static final int MSG_UPDATE_STATE = 0;
     private static final int MSG_ENABLE_ADB = 1;
-    private static final int MSG_SET_PRIMARY_FUNCTION = 2;
-    private static final int MSG_SET_DEFAULT_FUNCTION = 3;
-    private static final int MSG_SYSTEM_READY = 4;
+    private static final int MSG_SET_CURRENT_FUNCTION = 2;
+    private static final int MSG_SYSTEM_READY = 3;
 
     // Delay for debouncing USB disconnects.
     // We often get rapid connect/disconnect events when enabling USB functions,
@@ -227,7 +226,7 @@
                 mHandler.updateState(state);
             } else if ("START".equals(accessory)) {
                 Slog.d(TAG, "got accessory start");
-                setPrimaryFunction(UsbManager.USB_FUNCTION_ACCESSORY);
+                setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);
             }
         }
     };
@@ -371,6 +370,14 @@
             sendMessage(m);
         }
 
+        public void sendMessage(int what, Object arg0, boolean arg1) {
+            removeMessages(what);
+            Message m = Message.obtain(this, what);
+            m.obj = arg0;
+            m.arg1 = (arg1 ? 1 : 0);
+            sendMessage(m);
+        }
+
         public void updateState(String state) {
             int connected, configured;
 
@@ -395,24 +402,30 @@
             sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
         }
 
-        private boolean setUsbConfig(String config) {
-            // set the new configuration
-            SystemProperties.set("sys.usb.config", config);
+        private boolean waitForState(String state) {
             // wait for the transition to complete.
             // give up after 1 second.
             for (int i = 0; i < 20; i++) {
                 // State transition is done when sys.usb.conf.done is set to the new configuration
-                if (config.equals(SystemProperties.get("sys.usb.state"))) return true;
+                if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
                 try {
                     // try again in 50ms
                     Thread.sleep(50);
                 } catch (InterruptedException e) {
                 }
             }
+            Log.e(TAG, "waitForState(" + state + ") FAILED");
             return false;
         }
 
-        private void setCurrentFunctions(String functions) {
+        private boolean setUsbConfig(String config) {
+            Log.d(TAG, "setUsbConfig(" + config + ")");
+            // set the new configuration
+            SystemProperties.set("sys.usb.config", config);
+            return waitForState(config);
+        }
+
+        private void doSetCurrentFunctions(String functions) {
             if (!mCurrentFunctions.equals(functions)) {
                 if (!setUsbConfig("none") || !setUsbConfig(functions)) {
                     Log.e(TAG, "Failed to switch USB configuration to " + functions);
@@ -428,17 +441,14 @@
             if (enable != mAdbEnabled) {
                 mAdbEnabled = enable;
                 String functions;
+                // Due to the persist.sys.usb.config property trigger, changing adb state requires
+                // switching to default function
                 if (enable) {
-                    functions = addFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
-                    mDefaultFunctions = addFunction(mDefaultFunctions,
-                            UsbManager.USB_FUNCTION_ADB);
+                    functions = addFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
                 } else {
-                    functions = removeFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
-                    mDefaultFunctions = removeFunction(mDefaultFunctions,
-                            UsbManager.USB_FUNCTION_ADB);
+                    functions = removeFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
                 }
-                SystemProperties.set("persist.sys.usb.config", mDefaultFunctions);
-                setCurrentFunctions(functions);
+                setCurrentFunction(functions, true);
                 updateAdbNotification(mAdbEnabled && mConnected);
             }
         }
@@ -449,7 +459,7 @@
             } else {
                 functionList = removeFunction(functionList, UsbManager.USB_FUNCTION_ADB);
             }
-            setCurrentFunctions(functionList);
+            doSetCurrentFunctions(functionList);
         }
 
         private void updateCurrentAccessory() {
@@ -503,8 +513,6 @@
 
         @Override
         public void handleMessage(Message msg) {
-            String function;
-
             switch (msg.what) {
                 case MSG_UPDATE_STATE:
                     mConnected = (msg.arg1 == 1);
@@ -518,7 +526,7 @@
 
                     if (!mConnected) {
                         // restore defaults when USB is disconnected
-                        setCurrentFunctions(mDefaultFunctions);
+                        doSetCurrentFunctions(mDefaultFunctions);
                     }
                     if (mSystemReady) {
                         updateUsbState();
@@ -527,20 +535,31 @@
                 case MSG_ENABLE_ADB:
                     setAdbEnabled(msg.arg1 == 1);
                     break;
-                case MSG_SET_PRIMARY_FUNCTION:
-                    function = (String)msg.obj;
-                    if (function == null) {
-                        function = mDefaultFunctions;
+                case MSG_SET_CURRENT_FUNCTION:
+                    String function = (String)msg.obj;
+                    boolean makeDefault = (msg.arg1 == 1);
+                    if (makeDefault) {
+                        if (function == null) {
+                            throw new NullPointerException();
+                        }
+                        if (mAdbEnabled) {
+                            function = addFunction(function, UsbManager.USB_FUNCTION_ADB);
+                        }
+
+                        setUsbConfig("none");
+                        // setting this property will change the current USB state
+                        // via a property trigger
+                        SystemProperties.set("persist.sys.usb.config", function);
+                        if (waitForState(function)) {
+                            mCurrentFunctions = function;
+                            mDefaultFunctions = function;
+                        }
+                    } else {
+                        if (function == null) {
+                            function = mDefaultFunctions;
+                        }
+                        setEnabledFunctions(function);
                     }
-                    setEnabledFunctions(function);
-                    break;
-                case MSG_SET_DEFAULT_FUNCTION:
-                    function = (String)msg.obj;
-                    if (mAdbEnabled) {
-                        function = addFunction(function, UsbManager.USB_FUNCTION_ADB);
-                    }
-                    SystemProperties.set("persist.sys.usb.config", function);
-                    mDefaultFunctions = function;
                     break;
                 case MSG_SYSTEM_READY:
                     updateUsbNotification(mConnected);
@@ -588,15 +607,8 @@
             return nativeOpenAccessory();
         }
 
-    public void setPrimaryFunction(String function) {
-        mHandler.sendMessage(MSG_SET_PRIMARY_FUNCTION, function);
-    }
-
-    public void setDefaultFunction(String function) {
-        if (function == null) {
-            throw new NullPointerException();
-        }
-        mHandler.sendMessage(MSG_SET_DEFAULT_FUNCTION, function);
+    public void setCurrentFunction(String function, boolean makeDefault) {
+        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTION, function, makeDefault);
     }
 
     public void setMassStorageBackingFile(String path) {
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 193638f..9f2c17a 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -146,19 +146,10 @@
         mSettingsManager.clearDefaults(packageName);
     }
 
-    public void setPrimaryFunction(String function) {
+    public void setCurrentFunction(String function, boolean makeDefault) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
         if (mDeviceManager != null) {
-            mDeviceManager.setPrimaryFunction(function);
-        } else {
-            throw new IllegalStateException("USB device mode not supported");
-        }
-    }
-
-    public void setDefaultFunction(String function) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        if (mDeviceManager != null) {
-            mDeviceManager.setDefaultFunction(function);
+            mDeviceManager.setCurrentFunction(function, makeDefault);
         } else {
             throw new IllegalStateException("USB device mode not supported");
         }
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 3be8af6..6806634 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import android.graphics.Rect;
+import android.os.Binder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
@@ -152,6 +153,8 @@
         }
         mUpdateInputWindowsNeeded = false;
 
+        if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw");
+        
         // Populate the input window list with information about all of the windows that
         // could potentially receive input.
         // As an optimization, we could try to prune the list of windows but this turns
@@ -232,6 +235,8 @@
         // Clear the list in preparation for the next round.
         // Also avoids keeping InputChannel objects referenced unnecessarily.
         mTempInputWindows.clear();
+        
+        if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
     }
 
     /* Notifies that the input device configuration has changed. */
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 0f09356..50b251f 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -153,11 +153,13 @@
             int requestedWidth, int requestedHeight, int viewFlags,
             boolean insetsPending, Rect outFrame, Rect outContentInsets,
             Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
-        //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
+        if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from "
+                + Binder.getCallingPid());
         int res = mService.relayoutWindow(this, window, attrs,
                 requestedWidth, requestedHeight, viewFlags, insetsPending,
                 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
-        //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
+        if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to "
+                + Binder.getCallingPid());
         return res;
     }
 
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 1c87f5b..3bf309b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2776,6 +2776,13 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    public float getWindowCompatibilityScale(IBinder windowToken) {
+        synchronized (mWindowMap) {
+            WindowState windowState = mWindowMap.get(windowToken);
+            return (windowState != null) ? windowState.mGlobalScale : 1.0f;
+        }
+    }
+
     private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
                 + (lp != null ? lp.packageName : null)
@@ -5557,10 +5564,10 @@
 
     private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
             int dw, int dh) {
-        dm.unscaledWidthPixels = mPolicy.getNonDecorDisplayWidth(rotation, dw);
-        dm.unscaledHeightPixels = mPolicy.getNonDecorDisplayHeight(rotation, dh);
+        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(rotation, dw);
+        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(rotation, dh);
         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
-        int size = (int)(((dm.unscaledWidthPixels / scale) / dm.density) + .5f);
+        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
         if (curSize == 0 || size < curSize) {
             curSize = size;
         }
@@ -5635,9 +5642,9 @@
 
         // Override display width and height with what we are computing,
         // to be sure they remain consistent.
-        dm.widthPixels = dm.unscaledWidthPixels = mAppDisplayWidth
+        dm.widthPixels = dm.noncompatWidthPixels = mAppDisplayWidth
                 = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
-        dm.heightPixels = dm.unscaledHeightPixels = mAppDisplayHeight
+        dm.heightPixels = dm.noncompatHeightPixels = mAppDisplayHeight
                 = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
 
         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
@@ -7817,18 +7824,30 @@
                             TAG, "Placing surface #" + i + " " + w.mSurface
                             + ": new=" + w.mShownFrame);
 
-                    int width, height;
-                    if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
-                        // for a scaled surface, we just want to use
-                        // the requested size.
-                        width  = w.mRequestedWidth;
-                        height = w.mRequestedHeight;
-                    } else {
-                        width = w.mCompatFrame.width();
-                        height = w.mCompatFrame.height();
-                    }
-
                     if (w.mSurface != null) {
+                        int width, height;
+                        if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
+                            // for a scaled surface, we just want to use
+                            // the requested size.
+                            width  = w.mRequestedWidth;
+                            height = w.mRequestedHeight;
+                        } else {
+                            width = w.mCompatFrame.width();
+                            height = w.mCompatFrame.height();
+                        }
+
+                        if (width < 1) {
+                            width = 1;
+                        }
+                        if (height < 1) {
+                            height = 1;
+                        }
+                        final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height;
+                        if (surfaceResized) {
+                            w.mSurfaceW = width;
+                            w.mSurfaceH = height;
+                        }
+
                         if (w.mSurfaceX != w.mShownFrame.left
                                 || w.mSurfaceY != w.mShownFrame.top) {
                             try {
@@ -7848,21 +7867,11 @@
                             }
                         }
 
-                        if (width < 1) {
-                            width = 1;
-                        }
-                        if (height < 1) {
-                            height = 1;
-                        }
-
-                        if (w.mSurfaceW != width || w.mSurfaceH != height) {
+                        if (surfaceResized) {
                             try {
                                 if (SHOW_TRANSACTIONS) logSurface(w,
-                                        "SIZE " + w.mShownFrame.width() + "x"
-                                        + w.mShownFrame.height(), null);
+                                        "SIZE " + width + "x" + height, null);
                                 w.mSurfaceResized = true;
-                                w.mSurfaceW = width;
-                                w.mSurfaceH = height;
                                 w.mSurface.setSize(width, height);
                             } catch (RuntimeException e) {
                                 // If something goes wrong with the surface (such
@@ -7878,9 +7887,9 @@
                     }
 
                     if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
-                        w.mContentInsetsChanged =
+                        w.mContentInsetsChanged |=
                             !w.mLastContentInsets.equals(w.mContentInsets);
-                        w.mVisibleInsetsChanged =
+                        w.mVisibleInsetsChanged |=
                             !w.mLastVisibleInsets.equals(w.mVisibleInsets);
                         boolean configChanged =
                             w.mConfiguration != mCurConfiguration
@@ -7892,24 +7901,20 @@
                         }
                         if (localLOGV) Slog.v(TAG, "Resizing " + w
                                 + ": configChanged=" + configChanged
-                                + " last=" + w.mLastCompatFrame + " frame=" + w.mCompatFrame);
-                        boolean frameChanged = !w.mLastCompatFrame.equals(w.mCompatFrame);
-                        if (frameChanged
-                                || w.mContentInsetsChanged
+                                + " last=" + w.mLastFrame + " frame=" + w.mFrame);
+                        w.mLastFrame.set(w.mFrame);
+                        if (w.mContentInsetsChanged
                                 || w.mVisibleInsetsChanged
                                 || w.mSurfaceResized
                                 || configChanged) {
                             if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
                                 Slog.v(TAG, "Resize reasons: "
-                                        + "frameChanged=" + frameChanged
                                         + " contentInsetsChanged=" + w.mContentInsetsChanged
                                         + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
                                         + " surfaceResized=" + w.mSurfaceResized
                                         + " configChanged=" + configChanged);
                             }
 
-                            w.mLastFrame.set(w.mFrame);
-                            w.mLastCompatFrame.set(w.mCompatFrame);
                             w.mLastContentInsets.set(w.mContentInsets);
                             w.mLastVisibleInsets.set(w.mVisibleInsets);
                             // If the screen is currently frozen, then keep
@@ -7944,9 +7949,12 @@
                                     w.mAppToken.allDrawn = false;
                                 }
                             }
-                            if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
-                                    "Resizing window " + w + " to " + w.mCompatFrame);
-                            mResizingWindows.add(w);
+                            if (!mResizingWindows.contains(w)) {
+                                if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
+                                        "Resizing window " + w + " to " + w.mSurfaceW
+                                        + "x" + w.mSurfaceH);
+                                mResizingWindows.add(w);
+                            }
                         } else if (w.mOrientationChanging) {
                             if (!w.mDrawPending && !w.mCommitDrawPending) {
                                 if (DEBUG_ORIENTATION) Slog.v(TAG,
@@ -8241,13 +8249,12 @@
                     if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
                             && configChanged) {
                         Slog.i(TAG, "Sending new config to window " + win + ": "
-                                + win.mCompatFrame.width() + "x" + win.mCompatFrame.height()
+                                + win.mSurfaceW + "x" + win.mSurfaceH
                                 + " / " + mCurConfiguration + " / 0x"
                                 + Integer.toHexString(diff));
                     }
                     win.mConfiguration = mCurConfiguration;
-                    win.mClient.resized(win.mCompatFrame.width(),
-                            win.mCompatFrame.height(), win.mLastContentInsets,
+                    win.mClient.resized(win.mSurfaceW, win.mSurfaceH, win.mLastContentInsets,
                             win.mLastVisibleInsets, win.mDrawPending,
                             configChanged ? win.mConfiguration : null);
                     win.mContentInsetsChanged = false;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 587685e..b370ec9 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -111,7 +111,6 @@
      * applied).
      */
     final Rect mShownFrame = new Rect();
-    final Rect mLastShownFrame = new Rect();
 
     /**
      * Set when we have changed the size of the surface, to know that
@@ -182,7 +181,6 @@
     // Frame that is scaled to the application's coordinate space when in
     // screen size compatibility mode.
     final Rect mCompatFrame = new Rect();
-    final Rect mLastCompatFrame = new Rect();
 
     final Rect mContainingFrame = new Rect();
     final Rect mDisplayFrame = new Rect();
@@ -1584,15 +1582,12 @@
         }
         pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
         pw.print(prefix); pw.print("mShownFrame=");
-                mShownFrame.printShortString(pw);
-                pw.print(" last="); mLastShownFrame.printShortString(pw);
-                pw.println();
+                mShownFrame.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
                 pw.print(" last="); mLastFrame.printShortString(pw);
                 pw.println();
         if (mEnforceSizeCompat) {
             pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
-                    pw.print(" last="); mLastCompatFrame.printShortString(pw);
                     pw.println();
         }
         pw.print(prefix); pw.print("mContainingFrame=");
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index 6d4ad9a..87ffcba 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -42,6 +42,7 @@
 static jmethodID method_reportNiNotification;
 static jmethodID method_requestRefLocation;
 static jmethodID method_requestSetID;
+static jmethodID method_requestUtcTime;
 
 static const GpsInterface* sGpsInterface = NULL;
 static const GpsXtraInterface* sGpsXtraInterface = NULL;
@@ -122,6 +123,13 @@
     release_wake_lock(WAKE_LOCK_NAME);
 }
 
+static void request_utc_time_callback()
+{
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
 {
     return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
@@ -137,6 +145,7 @@
     acquire_wakelock_callback,
     release_wakelock_callback,
     create_thread_callback,
+    request_utc_time_callback,
 };
 
 static void xtra_download_request_callback()
@@ -232,6 +241,7 @@
             "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
     method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
     method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
+    method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
 
     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
     if (err == 0) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 0ae7929..64d214b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -31,6 +31,7 @@
 
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
 
 #include <gui/ISensorServer.h>
 #include <gui/ISensorEventConnection.h>
@@ -58,8 +59,7 @@
  */
 
 SensorService::SensorService()
-    : mDump("android.permission.DUMP"),
-      mInitCheck(NO_INIT)
+    : mInitCheck(NO_INIT)
 {
 }
 
@@ -166,12 +166,14 @@
         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 (!mDump.checkCalling()) {
+    if (!PermissionCache::checkCallingPermission(sDump)) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 4d0f1d9..85f4ecb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -27,7 +27,6 @@
 #include <utils/RefBase.h>
 
 #include <binder/BinderService.h>
-#include <binder/Permission.h>
 
 #include <gui/Sensor.h>
 #include <gui/SensorChannel.h>
@@ -117,7 +116,6 @@
     Vector<Sensor> mUserSensorList;
     DefaultKeyedVector<int, SensorInterface*> mSensorMap;
     Vector<SensorInterface *> mVirtualSensorList;
-    Permission mDump;
     status_t mInitCheck;
 
     // protected by mLock
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2bab6a8..35e29a6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -101,9 +101,8 @@
 }
 
 void Layer::onFrameQueued() {
-    if (android_atomic_or(1, &mQueuedFrames) == 0) {
-        mFlinger->signalEvent();
-    }
+    android_atomic_inc(&mQueuedFrames);
+    mFlinger->signalEvent();
 }
 
 // called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -406,20 +405,18 @@
 
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
 {
-    if (android_atomic_and(0, &mQueuedFrames)) {
+    if (mQueuedFrames > 0) {
+        // signal another event if we have more frames pending
+        if (android_atomic_dec(&mQueuedFrames) > 1) {
+            mFlinger->signalEvent();
+        }
+
         if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
             return;
         }
 
-        // signal another event if we have more frames waiting
-        if (mSurfaceTexture->getQueuedCount()) {
-            if (android_atomic_or(1, &mQueuedFrames) == 0) {
-                mFlinger->signalEvent();
-            }
-        }
-
         mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
         mSurfaceTexture->getTransformMatrix(mTextureMatrix);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 97edfee..1c57bc1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -32,6 +32,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
+#include <binder/PermissionCache.h>
 
 #include <utils/String8.h>
 #include <utils/String16.h>
@@ -67,17 +68,19 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
+const String16 sHardwareTest("android.permission.HARDWARE_TEST");
+const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
+const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
+const String16 sDump("android.permission.DUMP");
+
+// ---------------------------------------------------------------------------
+
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(), Thread(false),
         mTransactionFlags(0),
-        mTransactionCount(0),
         mResizeTransationPending(false),
         mLayersRemoved(false),
         mBootTime(systemTime()),
-        mHardwareTest("android.permission.HARDWARE_TEST"),
-        mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
-        mReadFramebuffer("android.permission.READ_FRAME_BUFFER"),
-        mDump("android.permission.DUMP"),
         mVisibleRegionsDirty(false),
         mHwWorkListDirty(false),
         mDeferReleaseConsole(false),
@@ -381,13 +384,11 @@
         handleConsoleEvents();
     }
 
-    if (LIKELY(mTransactionCount == 0)) {
-        // if we're in a global transaction, don't do anything.
-        const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
-        uint32_t transactionFlags = peekTransactionFlags(mask);
-        if (LIKELY(transactionFlags)) {
-            handleTransaction(transactionFlags);
-        }
+    // if we're in a global transaction, don't do anything.
+    const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+    uint32_t transactionFlags = peekTransactionFlags(mask);
+    if (UNLIKELY(transactionFlags)) {
+        handleTransaction(transactionFlags);
     }
 
     // post surfaces (if needed)
@@ -1172,28 +1173,33 @@
     return old;
 }
 
-void SurfaceFlinger::openGlobalTransaction()
-{
-    android_atomic_inc(&mTransactionCount);
-}
 
-void SurfaceFlinger::closeGlobalTransaction()
-{
-    if (android_atomic_dec(&mTransactionCount) == 1) {
-        signalEvent();
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) {
+    Mutex::Autolock _l(mStateLock);
 
-        // if there is a transaction with a resize, wait for it to
-        // take effect before returning.
-        Mutex::Autolock _l(mStateLock);
-        while (mResizeTransationPending) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                // just in case something goes wrong in SF, return to the
-                // called after a few seconds.
-                LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
-                mResizeTransationPending = false;
-                break;
-            }
+    uint32_t flags = 0;
+    const size_t count = state.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const ComposerState& s(state[i]);
+        sp<Client> client( static_cast<Client *>(s.client.get()) );
+        flags |= setClientStateLocked(client, s.state);
+    }
+    if (flags) {
+        setTransactionFlags(flags);
+    }
+
+    signalEvent();
+
+    // if there is a transaction with a resize, wait for it to
+    // take effect before returning.
+    while (mResizeTransationPending) {
+        status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+        if (CC_UNLIKELY(err != NO_ERROR)) {
+            // just in case something goes wrong in SF, return to the
+            // called after a few seconds.
+            LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+            mResizeTransationPending = false;
+            break;
         }
     }
 }
@@ -1389,60 +1395,52 @@
     return err;
 }
 
-status_t SurfaceFlinger::setClientState(
+uint32_t SurfaceFlinger::setClientStateLocked(
         const sp<Client>& client,
-        int32_t count,
-        const layer_state_t* states)
+        const layer_state_t& s)
 {
-    Mutex::Autolock _l(mStateLock);
     uint32_t flags = 0;
-    for (int i=0 ; i<count ; i++) {
-        const layer_state_t& s(states[i]);
-        sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
-        if (layer != 0) {
-            const uint32_t what = s.what;
-            if (what & ePositionChanged) {
-                if (layer->setPosition(s.x, s.y))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eLayerChanged) {
-                ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-                if (layer->setLayer(s.z)) {
-                    mCurrentState.layersSortedByZ.removeAt(idx);
-                    mCurrentState.layersSortedByZ.add(layer);
-                    // we need traversal (state changed)
-                    // AND transaction (list changed)
-                    flags |= eTransactionNeeded|eTraversalNeeded;
-                }
-            }
-            if (what & eSizeChanged) {
-                if (layer->setSize(s.w, s.h)) {
-                    flags |= eTraversalNeeded;
-                    mResizeTransationPending = true;
-                }
-            }
-            if (what & eAlphaChanged) {
-                if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eMatrixChanged) {
-                if (layer->setMatrix(s.matrix))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eTransparentRegionChanged) {
-                if (layer->setTransparentRegionHint(s.transparentRegion))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eVisibilityChanged) {
-                if (layer->setFlags(s.flags, s.mask))
-                    flags |= eTraversalNeeded;
+    sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
+    if (layer != 0) {
+        const uint32_t what = s.what;
+        if (what & ePositionChanged) {
+            if (layer->setPosition(s.x, s.y))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eLayerChanged) {
+            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+            if (layer->setLayer(s.z)) {
+                mCurrentState.layersSortedByZ.removeAt(idx);
+                mCurrentState.layersSortedByZ.add(layer);
+                // we need traversal (state changed)
+                // AND transaction (list changed)
+                flags |= eTransactionNeeded|eTraversalNeeded;
             }
         }
+        if (what & eSizeChanged) {
+            if (layer->setSize(s.w, s.h)) {
+                flags |= eTraversalNeeded;
+                mResizeTransationPending = true;
+            }
+        }
+        if (what & eAlphaChanged) {
+            if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eMatrixChanged) {
+            if (layer->setMatrix(s.matrix))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eTransparentRegionChanged) {
+            if (layer->setTransparentRegionHint(s.transparentRegion))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eVisibilityChanged) {
+            if (layer->setFlags(s.flags, s.mask))
+                flags |= eTraversalNeeded;
+        }
     }
-    if (flags) {
-        setTransactionFlags(flags);
-    }
-    return NO_ERROR;
+    return flags;
 }
 
 void SurfaceFlinger::screenReleased(int dpy)
@@ -1464,7 +1462,8 @@
     const size_t SIZE = 4096;
     char buffer[SIZE];
     String8 result;
-    if (!mDump.checkCalling()) {
+
+    if (!PermissionCache::checkCallingPermission(sDump)) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
@@ -1583,8 +1582,7 @@
 {
     switch (code) {
         case CREATE_CONNECTION:
-        case OPEN_GLOBAL_TRANSACTION:
-        case CLOSE_GLOBAL_TRANSACTION:
+        case SET_TRANSACTION_STATE:
         case SET_ORIENTATION:
         case FREEZE_DISPLAY:
         case UNFREEZE_DISPLAY:
@@ -1596,7 +1594,8 @@
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) {
+            if ((uid != AID_GRAPHICS) &&
+                    !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
                 LOGE("Permission Denial: "
                         "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                 return PERMISSION_DENIED;
@@ -1609,7 +1608,8 @@
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS) && !mReadFramebuffer.check(pid, uid)) {
+            if ((uid != AID_GRAPHICS) &&
+                    !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
                 LOGE("Permission Denial: "
                         "can't read framebuffer pid=%d, uid=%d", pid, uid);
                 return PERMISSION_DENIED;
@@ -1621,7 +1621,7 @@
     status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
         CHECK_INTERFACE(ISurfaceComposer, data, reply);
-        if (UNLIKELY(!mHardwareTest.checkCalling())) {
+        if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
@@ -2404,8 +2404,7 @@
      const int self_pid = getpid();
      if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
          // we're called from a different process, do the real check
-         if (!checkCallingPermission(
-                 String16("android.permission.ACCESS_SURFACE_FLINGER")))
+         if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
          {
              LOGE("Permission Denial: "
                      "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
@@ -2463,9 +2462,6 @@
 status_t Client::destroySurface(SurfaceID sid) {
     return mFlinger->removeSurface(this, sid);
 }
-status_t Client::setState(int32_t count, const layer_state_t* states) {
-    return mFlinger->setClientState(this, count, states);
-}
 
 // ---------------------------------------------------------------------------
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index af1ef04..b49fa36 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -20,21 +20,20 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
+#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
 
-#include <binder/IMemory.h>
-#include <binder/Permission.h>
 #include <binder/BinderService.h>
+#include <binder/IMemory.h>
 
 #include <ui/PixelFormat.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/ISurfaceComposerClient.h>
-#include <surfaceflinger/IGraphicBufferAlloc.h>
 
 #include "Barrier.h"
 #include "Layer.h"
@@ -71,14 +70,12 @@
     sp<LayerBaseClient> getLayerUser(int32_t i) const;
 
 private:
-
     // ISurfaceComposerClient interface
     virtual sp<ISurface> createSurface(
             surface_data_t* params, const String8& name,
             DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
             uint32_t flags);
     virtual status_t destroySurface(SurfaceID surfaceId);
-    virtual status_t setState(int32_t count, const layer_state_t* states);
     virtual status_t onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
 
@@ -169,8 +166,7 @@
     virtual sp<IGraphicBufferAlloc>     createGraphicBufferAlloc();
     virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
-    virtual void                        openGlobalTransaction();
-    virtual void                        closeGlobalTransaction();
+    virtual void                        setTransactionState(const Vector<ComposerState>& state);
     virtual status_t                    freezeDisplay(DisplayID dpy, uint32_t flags);
     virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);
@@ -221,8 +217,7 @@
 
     status_t removeSurface(const sp<Client>& client, SurfaceID sid);
     status_t destroySurface(const wp<LayerBaseClient>& layer);
-    status_t setClientState(const sp<Client>& client,
-            int32_t count, const layer_state_t* states);
+    uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
 
     class LayerVector : public SortedVector< sp<LayerBase> > {
     public:
@@ -338,7 +333,6 @@
     mutable     Mutex                   mStateLock;
                 State                   mCurrentState;
     volatile    int32_t                 mTransactionFlags;
-    volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
                 SortedVector< sp<LayerBase> > mLayerPurgatory;
                 bool                    mResizeTransationPending;
@@ -353,11 +347,7 @@
                 surface_flinger_cblk_t*     mServerCblk;
                 GLuint                      mWormholeTexName;
                 nsecs_t                     mBootTime;
-                Permission                  mHardwareTest;
-                Permission                  mAccessSurfaceFlinger;
-                Permission                  mReadFramebuffer;
-                Permission                  mDump;
-                
+
                 // Can only accessed from the main thread, these members
                 // don't need synchronization
                 State                       mDrawingState;
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 18c54b3..56b2a8f 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -43,9 +43,9 @@
             PIXEL_FORMAT_RGB_565);
 
 
-    client->openTransaction();
+    SurfaceComposerClient::openGlobalTransaction();
     surface->setLayer(100000);
-    client->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     Surface::SurfaceInfo info;
     surface->lock(&info);
@@ -57,9 +57,9 @@
     android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
     surface->unlockAndPost();
 
-    client->openTransaction();
+    SurfaceComposerClient::openGlobalTransaction();
     surface->setSize(320, 240);
-    client->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     
     IPCThreadState::self()->joinThreadPool();
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
index 5265f91..8e1c3fe 100644
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ b/services/surfaceflinger/tests/surface/surface.cpp
@@ -39,9 +39,9 @@
     
     sp<SurfaceControl> surfaceControl = client->createSurface(
             getpid(), 0, 160, 240, PIXEL_FORMAT_RGB_565);
-    client->openTransaction();
+    SurfaceComposerClient::openGlobalTransaction();
     surfaceControl->setLayer(100000);
-    client->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     // pretend it went cross-process
     Parcel parcel;
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_extended b/services/tests/servicestests/res/raw/xt_qtaguid_extended
new file mode 100644
index 0000000..5bef3dd
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_extended
@@ -0,0 +1,3 @@
+acct_tag_hex uid_tag_int iface rx_bytes rx_packets tx_bytes tx_packets teleported_goats
+0x0 1000 test0 1024 10 2048 20 2716057
+0x0000F00D00000000 1000 test0 512 5 512 5 3370318
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_typical b/services/tests/servicestests/res/raw/xt_qtaguid_typical
new file mode 100644
index 0000000..7c4f04e
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_typical
@@ -0,0 +1,32 @@
+idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes
+1 wlan0 0x0 0 14615 4270
+2 wlan0 0x0 1000 5175 915
+3 wlan0 0x0 1021 3381 903
+4 wlan0 0x0 10004 333821 53558
+5 wlan0 0x0 10010 4888 37363
+6 wlan0 0x0 10013 52 104
+7 wlan0 0x74182ada00000000 10004 18725 1066
+8 rmnet0 0x0 0 301274 30244
+9 rmnet0 0x0 1000 304 441
+10 rmnet0 0x0 1013 2880 2272
+11 rmnet0 0x0 1021 31407 8430
+12 rmnet0 0x0 10003 32665 3814
+13 rmnet0 0x0 10004 2373141 420112
+14 rmnet0 0x0 10010 870370 1111727
+15 rmnet0 0x0 10013 240 240
+16 rmnet0 0x0 10016 16703 13512
+17 rmnet0 0x0 10017 3990 3269
+18 rmnet0 0x0 10018 474504 14516062
+19 rmnet0 0x0 10019 782804 71077
+20 rmnet0 0x0 10022 70671 49684
+21 rmnet0 0x0 10029 5785354 397159
+22 rmnet0 0x0 10033 2102 1686
+23 rmnet0 0x0 10034 15495464 227694
+24 rmnet0 0x0 10037 31184994 684122
+25 rmnet0 0x0 10051 298687 113485
+26 rmnet0 0x0 10056 29504 20669
+27 rmnet0 0x0 10069 683 596
+28 rmnet0 0x0 10072 34051 12453
+29 rmnet0 0x0 10077 7025393 213866
+30 rmnet0 0x0 10081 354 1178
+31 rmnet0 0x74182ada00000000 10037 28507378 437004
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
new file mode 100644
index 0000000..ac7cb5a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import static com.android.server.NetworkManagementSocketTagger.tagToKernel;
+
+import android.content.res.Resources;
+import android.net.NetworkStats;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.frameworks.servicestests.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+/**
+ * Tests for {@link NetworkManagementService}.
+ */
+@LargeTest
+public class NetworkManagementServiceTest extends AndroidTestCase {
+    private File mTestProc;
+    private NetworkManagementService mService;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mTestProc = getContext().getFilesDir();
+        mService = NetworkManagementService.createForTest(mContext, mTestProc);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mService = null;
+
+        super.tearDown();
+    }
+
+    public void testNetworkStatsDetail() throws Exception {
+        stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
+
+        final NetworkStats stats = mService.getNetworkStatsDetail();
+        assertEquals(31, stats.size);
+        assertStatsEntry(stats, "wlan0", 0, 0, 14615L, 4270L);
+        assertStatsEntry(stats, "wlan0", 10004, 0, 333821L, 53558L);
+        assertStatsEntry(stats, "wlan0", 10004, 1947740890, 18725L, 1066L);
+        assertStatsEntry(stats, "rmnet0", 10037, 0, 31184994L, 684122L);
+        assertStatsEntry(stats, "rmnet0", 10037, 1947740890, 28507378L, 437004L);
+    }
+
+    public void testNetworkStatsDetailExtended() throws Exception {
+        stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats"));
+
+        final NetworkStats stats = mService.getNetworkStatsDetail();
+        assertEquals(2, stats.size);
+        assertStatsEntry(stats, "test0", 1000, 0, 1024L, 2048L);
+        assertStatsEntry(stats, "test0", 1000, 0xF00D, 512L, 512L);
+    }
+
+    public void testKernelTags() throws Exception {
+        assertEquals("0", tagToKernel(0x0));
+        assertEquals("214748364800", tagToKernel(0x32));
+        assertEquals("9223372032559808512", tagToKernel(Integer.MAX_VALUE));
+        assertEquals("0", tagToKernel(Integer.MIN_VALUE));
+        assertEquals("9223369837831520256", tagToKernel(Integer.MIN_VALUE - 512));
+
+        assertEquals(0, kernelToTag("0x0000000000000000"));
+        assertEquals(0x32, kernelToTag("0x0000003200000000"));
+        assertEquals(2147483647, kernelToTag("0x7fffffff00000000"));
+        assertEquals(0, kernelToTag("0x0000000000000000"));
+        assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000"));
+
+    }
+
+    /**
+     * Copy a {@link Resources#openRawResource(int)} into {@link File} for
+     * testing purposes.
+     */
+    private void stageFile(int rawId, File file) throws Exception {
+        new File(file.getParent()).mkdirs();
+        InputStream in = null;
+        OutputStream out = null;
+        try {
+            in = getContext().getResources().openRawResource(rawId);
+            out = new FileOutputStream(file);
+            Streams.copy(in, out);
+        } finally {
+            IoUtils.closeQuietly(in);
+            IoUtils.closeQuietly(out);
+        }
+    }
+
+    private static void assertStatsEntry(
+            NetworkStats stats, String iface, int uid, int tag, long rx, long tx) {
+        final int i = stats.findIndex(iface, uid, tag);
+        assertEquals(rx, stats.rx[i]);
+        assertEquals(tx, stats.tx[i]);
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 07e5425..b4ac987 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -41,7 +41,9 @@
 import android.app.INotificationManager;
 import android.app.IProcessObserver;
 import android.content.Intent;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.Signature;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyListener;
@@ -54,6 +56,7 @@
 import android.net.NetworkStats;
 import android.net.NetworkTemplate;
 import android.os.Binder;
+import android.os.INetworkManagementService;
 import android.os.IPowerManager;
 import android.test.AndroidTestCase;
 import android.test.mock.MockPackageManager;
@@ -63,12 +66,17 @@
 import android.util.TrustedTime;
 
 import com.android.server.net.NetworkPolicyManagerService;
+import com.google.common.util.concurrent.AbstractFuture;
 
 import org.easymock.Capture;
 import org.easymock.EasyMock;
+import org.easymock.IAnswer;
 
 import java.io.File;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Tests for {@link NetworkPolicyManagerService}.
@@ -88,6 +96,7 @@
     private IActivityManager mActivityManager;
     private IPowerManager mPowerManager;
     private INetworkStatsService mStatsService;
+    private INetworkManagementService mNetworkManagement;
     private INetworkPolicyListener mPolicyListener;
     private TrustedTime mTime;
     private IConnectivityManager mConnManager;
@@ -118,22 +127,40 @@
                     public String[] getPackagesForUid(int uid) {
                         return new String[] { "com.example" };
                     }
+
+                    @Override
+                    public PackageInfo getPackageInfo(String packageName, int flags) {
+                        final PackageInfo info = new PackageInfo();
+                        final Signature signature;
+                        if ("android".equals(packageName)) {
+                            signature = new Signature("F00D");
+                        } else {
+                            signature = new Signature("DEAD");
+                        }
+                        info.signatures = new Signature[] { signature };
+                        return info;
+                    }
                 };
             }
         };
 
         mPolicyDir = getContext().getFilesDir();
+        for (File file : mPolicyDir.listFiles()) {
+            file.delete();
+        }
 
         mActivityManager = createMock(IActivityManager.class);
         mPowerManager = createMock(IPowerManager.class);
         mStatsService = createMock(INetworkStatsService.class);
+        mNetworkManagement = createMock(INetworkManagementService.class);
         mPolicyListener = createMock(INetworkPolicyListener.class);
         mTime = createMock(TrustedTime.class);
         mConnManager = createMock(IConnectivityManager.class);
         mNotifManager = createMock(INotificationManager.class);
 
         mService = new NetworkPolicyManagerService(
-                mServiceContext, mActivityManager, mPowerManager, mStatsService, mTime, mPolicyDir);
+                mServiceContext, mActivityManager, mPowerManager, mStatsService,
+                mNetworkManagement, mTime, mPolicyDir);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
 
@@ -152,6 +179,9 @@
         expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
         expectTime(System.currentTimeMillis());
 
+        // default behavior is background data enabled
+        expect(mConnManager.getBackgroundDataSetting()).andReturn(true);
+
         replay();
         mService.systemReady();
         verifyAndReset();
@@ -228,81 +258,123 @@
     }
 
     public void testScreenChangesRules() throws Exception {
-        // push strict policy for foreground uid, verify ALLOW rule
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        Future<Void> future;
+
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
+        verifyAndReset();
+
+        // push strict policy for foreground uid, verify ALLOW rule
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // now turn screen off and verify REJECT rule
         expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+        future.get();
         verifyAndReset();
 
         // and turn screen back on, verify ALLOW rule restored
         expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+        future.get();
         verifyAndReset();
     }
 
     public void testPolicyNone() throws Exception {
+        Future<Void> future;
+
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
+        verifyAndReset();
+
         // POLICY_NONE should RULE_ALLOW in foreground
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mService.setUidPolicy(UID_A, POLICY_NONE);
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
         verifyAndReset();
 
         // POLICY_NONE should RULE_ALLOW in background
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        future.get();
         verifyAndReset();
     }
 
     public void testPolicyReject() throws Exception {
+        Future<Void> future;
+
         // POLICY_REJECT should RULE_ALLOW in background
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // POLICY_REJECT should RULE_ALLOW in foreground
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
         verifyAndReset();
 
         // POLICY_REJECT should RULE_REJECT in background
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        future.get();
         verifyAndReset();
     }
 
     public void testPolicyRejectAddRemove() throws Exception {
+        Future<Void> future;
+
         // POLICY_NONE should have RULE_ALLOW in background
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
-        mService.setUidPolicy(UID_A, POLICY_NONE);
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+        future.get();
         verifyAndReset();
 
         // adding POLICY_REJECT should cause RULE_REJECT
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // removing POLICY_REJECT should return us to RULE_ALLOW
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mService.setUidPolicy(UID_A, POLICY_NONE);
+        future.get();
         verifyAndReset();
     }
 
@@ -350,6 +422,7 @@
         long elapsedRealtime = 0;
         NetworkState[] state = null;
         NetworkStats stats = null;
+        Future<Void> future;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -360,10 +433,11 @@
         state = new NetworkState[] { buildWifi() };
         expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
         expectTime(TIME_MAR_10 + elapsedRealtime);
-        expectMeteredIfacesChanged();
+        future = expectMeteredIfacesChanged();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        future.get();
         verifyAndReset();
 
         // now change cycle to be on 15th, and test in early march, to verify we
@@ -377,30 +451,38 @@
         expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
                 .andReturn(stats).atLeastOnce();
 
-        // expect that quota remaining should be 1536 bytes
-        // TODO: write up NetworkManagementService mock
+        // TODO: consider making strongly ordered mock
+        expectRemoveInterfaceQuota(TEST_IFACE);
+        expectSetInterfaceQuota(TEST_IFACE, 1536L);
 
         expectClearNotifications();
-        expectMeteredIfacesChanged(TEST_IFACE);
+        future = expectMeteredIfacesChanged(TEST_IFACE);
 
         replay();
         setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
+        future.get();
         verifyAndReset();
     }
 
     public void testUidRemovedPolicyCleared() throws Exception {
+        Future<Void> future;
+
         // POLICY_REJECT should RULE_REJECT in background
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // uninstall should clear RULE_REJECT
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         final Intent intent = new Intent(ACTION_UID_REMOVED);
         intent.putExtra(EXTRA_UID, UID_A);
         mServiceContext.sendBroadcast(intent);
+        future.get();
         verifyAndReset();
     }
 
@@ -435,25 +517,62 @@
         expectLastCall().anyTimes();
     }
 
-    private void expectRulesChanged(int uid, int policy) throws Exception {
-        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+    private void expectSetInterfaceQuota(String iface, long quota) throws Exception {
+        mNetworkManagement.setInterfaceQuota(iface, quota);
         expectLastCall().atLeastOnce();
     }
 
-    private void expectMeteredIfacesChanged(String... ifaces) throws Exception {
-        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+    private void expectRemoveInterfaceQuota(String iface) throws Exception {
+        mNetworkManagement.removeInterfaceQuota(iface);
         expectLastCall().atLeastOnce();
     }
 
+    private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
+            throws Exception {
+        mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+        expectLastCall().atLeastOnce();
+    }
+
+    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+        expectLastCall().andAnswer(future);
+        return future;
+    }
+
+    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+        expectLastCall().andAnswer(future);
+        return future;
+    }
+
+    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
+        @Override
+        public Void get() throws InterruptedException, ExecutionException {
+            try {
+                return get(5, TimeUnit.SECONDS);
+            } catch (TimeoutException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public Void answer() {
+            set(null);
+            return null;
+        }
+    }
+
     private void replay() {
-        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
-                mConnManager, mNotifManager);
+        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+                mNetworkManagement, mTime, mConnManager, mNotifManager);
     }
 
     private void verifyAndReset() {
-        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
-                mConnManager, mNotifManager);
-        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
-                mConnManager, mNotifManager);
+        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+                mNetworkManagement, mTime, mConnManager, mNotifManager);
+        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+                mNetworkManagement, mTime, mConnManager, mNotifManager);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 636d059..903f2b0 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -59,7 +59,6 @@
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
 import android.util.TrustedTime;
 
 import com.android.server.net.NetworkStatsService;
@@ -611,6 +610,9 @@
         mAlarmManager.setInexactRepeating(
                 eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
         expectLastCall().atLeastOnce();
+
+        mNetManager.setBandwidthControlEnabled(true);
+        expectLastCall().atLeastOnce();
     }
 
     private void expectNetworkState(NetworkState... state) throws Exception {
@@ -631,6 +633,7 @@
 
     private void expectSettings(long persistThreshold, long bucketDuration, long maxHistory)
             throws Exception {
+        expect(mSettings.getEnabled()).andReturn(true).anyTimes();
         expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes();
         expect(mSettings.getPersistThreshold()).andReturn(persistThreshold).anyTimes();
         expect(mSettings.getNetworkBucketDuration()).andReturn(bucketDuration).anyTimes();
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index ffabb7b..dea67f3 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -94,6 +94,9 @@
      */
     public PhoneNumberFormattingTextWatcher(String countryCode) {
         if (countryCode == null) throw new IllegalArgumentException();
+        // TODO: remove this once CountryDetector.detectCountry().getCountryIso() is fixed to always
+        // return uppercase. Tracked at b/4941319.
+        countryCode = countryCode.toUpperCase(Locale.ENGLISH);
         mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 184d665..66120a1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -191,10 +191,6 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceId() {
-        if (!isVoiceCapable()) {
-            return null;
-        }
-
         try {
             return getSubscriberInfo().getDeviceId();
         } catch (RemoteException ex) {
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index 496c43c..a52f1ca 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.telephony;
 
-import android.app.PendingIntent;
-
 import android.util.Log;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -49,8 +47,6 @@
 
     String mReason;
 
-    PendingIntent mReconnectIntent;
-
     /**
      * user/app requested connection on this APN
      */
@@ -89,6 +85,11 @@
     }
 
     public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
+        if (dcac != null) {
+            dcac.addApnContextSync(this);
+        } else {
+            if (mDataConnectionAc != null) mDataConnectionAc.removeApnContextSync(this);
+        }
         mDataConnectionAc = dcac;
     }
 
@@ -164,16 +165,6 @@
         return mReason;
     }
 
-    public synchronized void setReconnectIntent(PendingIntent intent) {
-        if (DBG)
-            log("set ReconnectIntent for type " + mApnType);
-        mReconnectIntent = intent;
-    }
-
-    public synchronized PendingIntent getReconnectIntent() {
-        return mReconnectIntent;
-    }
-
     public boolean isReady() {
         return mDataEnabled.get() && mDependencyMet.get();
     }
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 457fa7aa..ab93e2a 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -30,8 +30,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
 import com.google.i18n.phonenumbers.NumberParseException;
-import com.google.i18n.phonenumbers.PhoneNumberOfflineGeocoder;
 import com.google.i18n.phonenumbers.PhoneNumberUtil;
 import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
 
@@ -526,8 +526,20 @@
                   + countryIso);
         }
 
+        // Temp workaround: The current libphonenumber library requires
+        // the countryIso to be uppercase (e.g. "US") but the
+        // detector.detectCountry().getCountryIso() call currently returns
+        // "us".  Passing "us" to util.parse() will just result in a
+        // NumberParseException.
+        // So force the countryIso to uppercase for now.
+        // TODO: remove this once getCountryIso() is fixed to always
+        // return uppercase.
+        countryIso = countryIso.toUpperCase();
+
         PhoneNumber pn = null;
         try {
+            if (VDBG) Log.v(TAG, "parsing '" + number
+                            + "' for countryIso '" + countryIso + "'...");
             pn = util.parse(number, countryIso);
             if (VDBG) Log.v(TAG, "- parsed number: " + pn);
         } catch (NumberParseException e) {
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 1bd9b0c..2e8a742 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -55,7 +55,7 @@
     // PhoneNumberOfflineGeocoder to look up a "geo description"?
     // (TODO: This could become a flag in config.xml if it ever needs to be
     // configured on a per-product basis.)
-    private static final boolean ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION = false;
+    private static final boolean ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION = true;
 
     /**
      * Interface for a CallerInfoAsyncQueryHandler result return.
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index f5651e0..fba3184 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -47,6 +47,7 @@
     public String [] addresses = new String[0];
     public String [] dnses = new String[0];
     public String[] gateways = new String[0];
+    public int suggestedRetryTime = -1;
 
     /**
      * Class returned by onSetupConnectionCompleted.
@@ -77,6 +78,7 @@
         sb.append("DataCallState: {")
            .append("version=").append(version)
            .append(" status=").append(status)
+           .append(" retry=").append(suggestedRetryTime)
            .append(" cid=").append(cid)
            .append(" active=").append(active)
            .append(" type=").append(type)
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 5c030fd..5c84fdc 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -22,6 +22,7 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
+import android.app.PendingIntent;
 import android.net.LinkAddress;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
@@ -35,8 +36,10 @@
 import android.os.SystemProperties;
 import android.text.TextUtils;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -68,6 +71,8 @@
     protected static int mCount;
     protected AsyncChannel mAc;
 
+    private List<ApnContext> mApnList = null;
+    PendingIntent mReconnectIntent = null;
 
     /**
      * Used internally for saving connecting parameters.
@@ -182,6 +187,18 @@
         }
     }
 
+    public static class CallSetupException extends Exception {
+        private int mRetryOverride = -1;
+
+        CallSetupException (int retryOverride) {
+            mRetryOverride = retryOverride;
+        }
+
+        public int getRetryOverride() {
+            return mRetryOverride;
+        }
+    }
+
     // ***** Event codes for driving the state machine
     protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
     protected static final int EVENT_CONNECT = BASE + 0;
@@ -205,6 +222,7 @@
     protected long createTime;
     protected long lastFailTime;
     protected FailCause lastFailCause;
+    protected int mRetryOverride = -1;
     protected static final String NULL_IP = "0.0.0.0";
     private int mRefCount;
     Object userData;
@@ -237,6 +255,8 @@
             addState(mDisconnectingState, mDefaultState);
             addState(mDisconnectingErrorCreatingConnection, mDefaultState);
         setInitialState(mInactiveState);
+
+        mApnList = new ArrayList<ApnContext>();
         if (DBG) log("DataConnection constructor X");
     }
 
@@ -288,7 +308,8 @@
         } else {
             lastFailCause = cause;
             lastFailTime = timeStamp;
-            AsyncResult.forMessage(connectionCompletedMsg, cause, new Exception());
+            AsyncResult.forMessage(connectionCompletedMsg, cause,
+                                   new CallSetupException(mRetryOverride));
         }
         if (DBG) log("notifyConnectionCompleted at " + timeStamp + " cause=" + cause);
 
@@ -430,6 +451,7 @@
         createTime = -1;
         lastFailTime = -1;
         lastFailCause = FailCause.NONE;
+        mRetryOverride = -1;
         mRefCount = 0;
 
         mLinkProperties = new LinkProperties();
@@ -482,6 +504,15 @@
         return result;
     }
 
+    private int getSuggestedRetryTime(AsyncResult ar) {
+        int retry = -1;
+        if (ar.exception == null) {
+            DataCallState response = (DataCallState) ar.result;
+            retry =  response.suggestedRetryTime;
+        }
+        return retry;
+    }
+
     private DataCallState.SetupResult setLinkProperties(DataCallState response,
             LinkProperties lp) {
         // Check if system property dns usable
@@ -638,7 +669,41 @@
                     mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
                     break;
                 }
-
+                case DataConnectionAc.REQ_ADD_APNCONTEXT: {
+                    ApnContext apnContext = (ApnContext) msg.obj;
+                    if (VDBG) log("REQ_ADD_APNCONTEXT apn=" + apnContext.getApnType());
+                    if (!mApnList.contains(apnContext)) {
+                        mApnList.add(apnContext);
+                    }
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_ADD_APNCONTEXT);
+                    break;
+                }
+                case DataConnectionAc.REQ_REMOVE_APNCONTEXT: {
+                    ApnContext apnContext = (ApnContext) msg.obj;
+                    if (VDBG) log("REQ_REMOVE_APNCONTEXT apn=" + apnContext.getApnType());
+                    mApnList.remove(apnContext);
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_REMOVE_APNCONTEXT);
+                    break;
+                }
+                case DataConnectionAc.REQ_GET_APNCONTEXT_LIST: {
+                    if (VDBG) log("REQ_GET_APNCONTEXT_LIST num in list=" + mApnList.size());
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNCONTEXT_LIST,
+                                       new ArrayList(mApnList));
+                    break;
+                }
+                case DataConnectionAc.REQ_SET_RECONNECT_INTENT: {
+                    PendingIntent intent = (PendingIntent) msg.obj;
+                    if (VDBG) log("REQ_SET_RECONNECT_INTENT");
+                    mReconnectIntent = intent;
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_RECONNECT_INTENT);
+                    break;
+                }
+                case DataConnectionAc.REQ_GET_RECONNECT_INTENT: {
+                    if (VDBG) log("REQ_GET_RECONNECT_INTENT");
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_RECONNECT_INTENT,
+                                       mReconnectIntent);
+                    break;
+                }
                 case EVENT_CONNECT:
                     if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
                     ConnectionParams cp = (ConnectionParams) msg.obj;
@@ -685,10 +750,12 @@
         private FailCause mFailCause = null;
         private DisconnectParams mDisconnectParams = null;
 
-        public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
+        public void setEnterNotificationParams(ConnectionParams cp, FailCause cause,
+                                               int retryOverride) {
             if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
             mConnectionParams = cp;
             mFailCause = cause;
+            mRetryOverride = retryOverride;
         }
 
         public void setEnterNotificationParams(DisconnectParams dp) {
@@ -808,7 +875,7 @@
                             // Vendor ril rejected the command and didn't connect.
                             // Transition to inactive but send notifications after
                             // we've entered the mInactive state.
-                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause, -1);
                             transitionTo(mInactiveState);
                             break;
                         case ERR_UnacceptableParameter:
@@ -823,7 +890,8 @@
                             break;
                         case ERR_RilError:
                             // Request failed and mFailCause has the reason
-                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause,
+                                                                      getSuggestedRetryTime(ar));
                             transitionTo(mInactiveState);
                             break;
                         case ERR_Stale:
@@ -848,8 +916,8 @@
                         }
                         // Transition to inactive but send notifications after
                         // we've entered the mInactive state.
-                         mInactiveState.setEnterNotificationParams(cp, cause);
-                         transitionTo(mInactiveState);
+                        mInactiveState.setEnterNotificationParams(cp, cause, -1);
+                        transitionTo(mInactiveState);
                     } else {
                         if (DBG) {
                             log("DcActivatingState EVENT_GET_LAST_FAIL_DONE is stale cp.tag="
@@ -1016,7 +1084,7 @@
                         // Transition to inactive but send notifications after
                         // we've entered the mInactive state.
                         mInactiveState.setEnterNotificationParams(cp,
-                                FailCause.UNACCEPTABLE_NETWORK_PARAMETER);
+                                FailCause.UNACCEPTABLE_NETWORK_PARAMETER, -1);
                         transitionTo(mInactiveState);
                     } else {
                         if (DBG) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
index 62b90ae..309dbed6 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionAc.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -19,11 +19,15 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
+import android.app.PendingIntent;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.ProxyProperties;
 import android.os.Message;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 /**
  * AsyncChannel to a DataConnection
  */
@@ -62,6 +66,21 @@
     public static final int REQ_GET_REFCOUNT = BASE + 16;
     public static final int RSP_GET_REFCOUNT = BASE + 17;
 
+    public static final int REQ_ADD_APNCONTEXT = BASE + 18;
+    public static final int RSP_ADD_APNCONTEXT = BASE + 19;
+
+    public static final int REQ_REMOVE_APNCONTEXT = BASE + 20;
+    public static final int RSP_REMOVE_APNCONTEXT = BASE + 21;
+
+    public static final int REQ_GET_APNCONTEXT_LIST = BASE + 22;
+    public static final int RSP_GET_APNCONTEXT_LIST = BASE + 23;
+
+    public static final int REQ_SET_RECONNECT_INTENT = BASE + 24;
+    public static final int RSP_SET_RECONNECT_INTENT = BASE + 25;
+
+    public static final int REQ_GET_RECONNECT_INTENT = BASE + 26;
+    public static final int RSP_GET_RECONNECT_INTENT = BASE + 27;
+
     /**
      * enum used to notify action taken or necessary to be
      * taken after the link property is changed.
@@ -371,6 +390,150 @@
         }
     }
 
+    /**
+     * Request to add ApnContext association.
+     * Response RSP_ADD_APNCONTEXT when complete.
+     */
+    public void reqAddApnContext(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
+        if (DBG) log("reqAddApnContext");
+    }
+
+    /**
+     * Add ApnContext association synchronoulsy.
+     *
+     * @param ApnContext to associate
+     */
+    public void addApnContextSync(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
+        if ((response != null) && (response.what == RSP_ADD_APNCONTEXT)) {
+            if (DBG) log("addApnContext ok");
+        } else {
+            log("addApnContext error response=" + response);
+        }
+    }
+
+    /**
+     * Request to remove ApnContext association.
+     * Response RSP_REMOVE_APNCONTEXT when complete.
+     */
+    public void reqRemomveApnContext(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
+        if (DBG) log("reqRemomveApnContext");
+    }
+
+    /**
+     * Remove ApnContext associateion.
+     *
+     * @param ApnContext to dissociate
+     */
+    public void removeApnContextSync(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
+        if ((response != null) && (response.what == RSP_REMOVE_APNCONTEXT)) {
+            if (DBG) log("removeApnContext ok");
+        } else {
+            log("removeApnContext error response=" + response);
+        }
+    }
+
+    /**
+     * Request to retrive ApnContext List associated with DC.
+     * Response RSP_GET_APNCONTEXT_LIST when complete.
+     */
+    public void reqGetApnList(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
+        if (DBG) log("reqGetApnList");
+    }
+
+    /**
+     * Retrieve Collection of ApnContext from the response message.
+     *
+     * @param Message sent from DC in response to REQ_GET_APNCONTEXT_LIST.
+     * @return Collection of ApnContext
+     */
+    public Collection<ApnContext> rspApnList(Message response) {
+        Collection<ApnContext> retVal = (Collection<ApnContext>)response.obj;
+        if (retVal == null) retVal = new ArrayList<ApnContext>();
+        return retVal;
+    }
+
+    /**
+     * Retrieve collection of ApnContext currently associated with
+     * the DataConnectionA synchronously.
+     *
+     * @return Collection of ApnContext
+     */
+    public Collection<ApnContext> getApnListSync() {
+        Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
+        if ((response != null) && (response.what == RSP_GET_APNCONTEXT_LIST)) {
+            if (DBG) log("getApnList ok");
+            return rspApnList(response);
+        } else {
+            log("getApnList error response=" + response);
+            // return dummy list with no entry
+            return new ArrayList<ApnContext>();
+        }
+    }
+
+    /**
+     * Request to set Pending ReconnectIntent to DC.
+     * Response RSP_SET_RECONNECT_INTENT when complete.
+     */
+    public void reqSetReconnectIntent(PendingIntent intent) {
+        Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
+        if (DBG) log("reqSetReconnectIntent");
+    }
+
+    /**
+     * Set pending reconnect intent to DC synchronously.
+     *
+     * @param PendingIntent to set.
+     */
+    public void setReconnectIntentSync(PendingIntent intent) {
+        Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
+        if ((response != null) && (response.what == RSP_SET_RECONNECT_INTENT)) {
+            if (DBG) log("setReconnectIntent ok");
+        } else {
+            log("setReconnectIntent error response=" + response);
+        }
+    }
+
+    /**
+     * Request to get Pending ReconnectIntent to DC.
+     * Response RSP_GET_RECONNECT_INTENT when complete.
+     */
+    public void reqGetReconnectIntent() {
+        Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
+        if (DBG) log("reqGetReconnectIntent");
+    }
+
+    /**
+     * Retrieve reconnect intent from response message from DC.
+     *
+     * @param Message which contains the reconnect intent.
+     * @return PendingIntent from the response.
+     */
+    public PendingIntent rspReconnectIntent(Message response) {
+        PendingIntent retVal = (PendingIntent) response.obj;
+        return retVal;
+    }
+
+    /**
+     * Retrieve reconnect intent currently set in DC synchronously.
+     *
+     * @return PendingIntent reconnect intent current ly set in DC
+     */
+    public PendingIntent getReconnectIntentSync() {
+        Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
+        if ((response != null) && (response.what == RSP_GET_RECONNECT_INTENT)) {
+            if (DBG) log("getReconnectIntent ok");
+            return rspReconnectIntent(response);
+        } else {
+            log("getReconnectIntent error response=" + response);
+            return null;
+        }
+    }
+
     private void log(String s) {
         android.util.Log.d(mLogTag, "DataConnectionAc " + s);
     }
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 76f1ab7..c6ed405 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -3009,6 +3009,7 @@
             }
         } else {
             dataCall.status = p.readInt();
+            dataCall.suggestedRetryTime = p.readInt();
             dataCall.cid = p.readInt();
             dataCall.active = p.readInt();
             dataCall.type = p.readString();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 6a95b67..a31b704 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -129,6 +129,12 @@
         super.setSystemLocale(language, country, false);
     }
 
+    // return IMSI from USIM as subscriber ID.
+    @Override
+    public String getSubscriberId() {
+        return mIccRecords.getIMSI();
+    }
+
     @Override
     protected void log(String s) {
         if (DBG)
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 19c06f6..5fc0bf9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -68,7 +68,9 @@
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
 
@@ -123,14 +125,20 @@
         if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
 
         String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
-        String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
-        ApnContext apnContext = mApnContexts.get(type);
-        if (apnContext != null) {
-            apnContext.setReason(reason);
-            if (apnContext.getState() == State.FAILED) {
-                apnContext.setState(State.IDLE);
+        int connectionId = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, -1);
+
+        DataConnectionAc dcac= mDataConnectionAsyncChannels.get(connectionId);
+
+        if (dcac != null) {
+            for (ApnContext apnContext : dcac.getApnListSync()) {
+                apnContext.setReason(reason);
+                if (apnContext.getState() == State.FAILED) {
+                    apnContext.setState(State.IDLE);
+                }
+                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
             }
-            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
+            // Alram had expired. Clear pending intent recorded on the DataConnection.
+            dcac.setReconnectIntentSync(null);
         }
     }
 
@@ -589,17 +597,25 @@
     }
 
     private void setupDataOnReadyApns(String reason) {
+        // Stop reconnect alarms on all data connections pending
+        // retry. Reset ApnContext state to IDLE.
+        for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+            if (dcac.getReconnectIntentSync() != null) {
+                cancelReconnectAlarm(dcac);
+                if (dcac.dataConnection != null) {
+                    dcac.dataConnection.resetRetryCount();
+                }
+
+                Collection<ApnContext> apnList = dcac.getApnListSync();
+                for (ApnContext apnContext : apnList) {
+                    apnContext.setState(State.IDLE);
+                }
+            }
+        }
+
         // Only check for default APN state
         for (ApnContext apnContext : mApnContexts.values()) {
             if (apnContext.isReady()) {
-                if (apnContext.getState() == State.FAILED) {
-                    cleanApnContextBeforeRestart(apnContext);
-                    if (apnContext.getDataConnection() != null) {
-                        apnContext.getDataConnection().resetRetryCount();
-                    }
-                }
-                // Do not start ApnContext in SCANNING state
-                // FAILED state must be reset to IDLE by now
                 if (apnContext.getState() == State.IDLE) {
                     apnContext.setReason(reason);
                     trySetupData(apnContext);
@@ -749,53 +765,70 @@
         if (DBG) {
             log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
         }
-        if (tearDown && cleanApnContextBeforeRestart(apnContext)) {
-            // if the request is tearDown and ApnContext does not hold an active connection,
-            // we're ok to return here.
-            return;
-        }
-
         DataConnectionAc dcac = apnContext.getDataConnectionAc();
-        if (tearDown && (dcac != null)) {
-            if (DBG) log("cleanUpConnection: tearing down");
-            Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
-            apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
-            apnContext.setState(State.DISCONNECTING);
+        if (tearDown) {
+            boolean isConnected = (apnContext.getState() != State.IDLE
+                                   && apnContext.getState() != State.FAILED);
+            if (!isConnected) {
+                // The request is tearDown and but ApnContext is not connected.
+                // If apnContext is not enabled anymore, break the linkage to the DCAC/DC.
+                apnContext.setState(State.IDLE);
+                if (!apnContext.isReady()) {
+                    apnContext.setDataConnection(null);
+                    apnContext.setDataConnectionAc(null);
+                }
+            } else {
+                // Connection is still there. Try to clean up.
+                if (dcac != null) {
+                    if (apnContext.getState() != State.DISCONNECTING) {
+                        if (DBG) log("cleanUpConnection: tearing down");
+                        Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+                        apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+                        apnContext.setState(State.DISCONNECTING);
+                    } else {
+                        // apn is connected but no reference to dcac.
+                        // Should not be happen, but reset the state in case.
+                        apnContext.setState(State.IDLE);
+                        mPhone.notifyDataConnection(apnContext.getReason(),
+                                                    apnContext.getApnType());
+                    }
+                }
+            }
         } else {
+            // force clean up the data connection.
             if (dcac != null) dcac.resetSync();
             apnContext.setState(State.IDLE);
             mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
             apnContext.setDataConnection(null);
             apnContext.setDataConnectionAc(null);
         }
+
+        // make sure reconnection alarm is cleaned up if there is no ApnContext
+        // associated to the connection.
+        if (dcac != null) {
+            Collection<ApnContext> apnList = dcac.getApnListSync();
+            if (apnList.isEmpty()) {
+                cancelReconnectAlarm(dcac);
+            }
+        }
     }
 
     /**
-     * @param APNContext to clean
-     * @return true if ApnContext is not connected anymore.
-     *         false if ApnContext still holds a connection.
+     * Cancels the alarm associated with DCAC.
+     *
+     * @param DataConnectionAc on which the alarm should be stopped.
      */
-    private boolean cleanApnContextBeforeRestart(ApnContext apnContext) {
-        if (apnContext == null) return true;
+    private void cancelReconnectAlarm(DataConnectionAc dcac) {
+        if (dcac == null) return;
 
-        // Clear the reconnect alarm, if set.
-        if (apnContext.getReconnectIntent() != null) {
-            AlarmManager am =
-                (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-            am.cancel(apnContext.getReconnectIntent());
-            apnContext.setReconnectIntent(null);
-        }
+        PendingIntent intent = dcac.getReconnectIntentSync();
 
-        if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
-            if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
-            return true;
+        if (intent != null) {
+                AlarmManager am =
+                    (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+                am.cancel(intent);
+                dcac.setReconnectIntentSync(null);
         }
-
-        if (apnContext.getState() == State.FAILED) {
-            apnContext.setState(State.IDLE);
-            return true;
-        }
-        return false;
     }
 
     /**
@@ -844,9 +877,16 @@
         return result;
     }
 
+    private boolean dataConnectionNotInUse(DataConnectionAc dcac) {
+        for (ApnContext apnContext : mApnContexts.values()) {
+            if (apnContext.getDataConnectionAc() == dcac) return false;
+        }
+        return true;
+    }
+
     private GsmDataConnection findFreeDataConnection() {
         for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
-            if (dcac.isInactiveSync()) {
+            if (dcac.isInactiveSync() && dataConnectionNotInUse(dcac)) {
                 log("findFreeDataConnection: found free GsmDataConnection");
                 return (GsmDataConnection) dcac.dataConnection;
             }
@@ -926,18 +966,27 @@
             if (refCount == 0) {
                 configureRetry(dc, apnContext.getApnType());
             }
-            apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId()));
-            apnContext.setApnSetting(apn);
+            apnContext.setDataConnectionAc(dcac);
             apnContext.setDataConnection(dc);
         }
 
+        apnContext.setApnSetting(apn);
+        apnContext.setState(State.INITING);
+        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+        // If reconnect alarm is active on this DataConnection, wait for the alarm being
+        // fired so that we don't disruppt data retry pattern engaged.
+        if (apnContext.getDataConnectionAc().getReconnectIntentSync() != null) {
+            if (DBG) log("setupData: data reconnection pending");
+            apnContext.setState(State.FAILED);
+            mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+            return true;
+        }
+
         Message msg = obtainMessage();
         msg.what = EVENT_DATA_SETUP_COMPLETE;
         msg.obj = apnContext;
         dc.bringUp(msg, apn);
 
-        apnContext.setState(State.INITING);
-        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
         if (DBG) log("setupData: initing!");
         return true;
     }
@@ -969,6 +1018,49 @@
     }
 
     /**
+     * @param cid Connection id provided from RIL.
+     * @return DataConnectionAc associated with specified cid.
+     */
+    private DataConnectionAc findDataConnectionAcByCid(int cid) {
+        for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+            if (dcac.getCidSync() == cid) {
+                return dcac;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @param dcacs Collection of DataConnectionAc reported from RIL.
+     * @return List of ApnContext whihc is connected, but does not present in
+     *         data connection list reported from RIL.
+     */
+    private List<ApnContext> findApnContextToClean(Collection<DataConnectionAc> dcacs) {
+        if (dcacs == null) return null;
+
+        ArrayList<ApnContext> list = new ArrayList<ApnContext>();
+        for (ApnContext apnContext : mApnContexts.values()) {
+            if (apnContext.getState() == State.CONNECTED) {
+                boolean found = false;
+                for (DataConnectionAc dcac : dcacs) {
+                    if (dcac == apnContext.getDataConnectionAc()) {
+                        // ApnContext holds the ref to dcac present in data call list.
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    // ApnContext does not have dcan reorted in data call list.
+                    if (DBG) log("onDataStateChanged(ar): Connected apn not found in the list (" +
+                                 apnContext.toString() + ")");
+                    list.add(apnContext);
+                }
+            }
+        }
+        return list;
+    }
+
+    /**
      * @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
      * or RIL_UNSOL_DATA_CALL_LIST_CHANGED
      */
@@ -985,91 +1077,102 @@
             if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
             return;
         }
+        if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
 
-        // Create a hash map to store the dataCallState of each call id
+        // Create a hash map to store the dataCallState of each DataConnectionAc
         // TODO: Depends on how frequent the DATA_CALL_LIST got updated,
         //       may cache response to reduce comparison.
-        HashMap<Integer, DataCallState> response;
-        response = new HashMap<Integer, DataCallState>();
-        if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
-        for (DataCallState dc : dataCallStates) {
-            response.put(dc.cid, dc);
-            if (DBG) log("onDataStateChanged(ar): " + dc.cid + ": " + dc.toString());
+        HashMap<DataCallState, DataConnectionAc> response;
+        response = new HashMap<DataCallState, DataConnectionAc>();
+        for (DataCallState dataCallState : dataCallStates) {
+            DataConnectionAc dcac = findDataConnectionAcByCid(dataCallState.cid);
+
+            if (dcac != null) response.put(dataCallState, dcac);
         }
 
-        // For each connected apn, check if there is a matched active
-        // data call state, which has the same link properties.
-        if (DBG) log("    ApnContext size=" + mApnContexts.values().size());
-        for (ApnContext apnContext : mApnContexts.values()) {
-            if (DBG){
-                log("onDataStateChanged(ar): " + apnContext.toString());
-                if (apnContext.getDataConnection() != null) {
-                    log("onDataStateChanged(ar): " +  apnContext.getDataConnection().toString());
+        // step1: Find a list of "connected" APN which does not have reference to
+        //        calls listed in the Data Call List.
+        List<ApnContext> apnsToClear = findApnContextToClean(response.values());
+
+        // step2: Check status of each calls in Data Call List.
+        //        Collect list of ApnContext associated with the data call if the link
+        //        has to be cleared.
+        for (DataCallState newState : dataCallStates) {
+            DataConnectionAc dcac = response.get(newState);
+
+            // no associated DataConnection found. Ignore.
+            if (dcac == null) continue;
+
+            Collection<ApnContext> apns = dcac.getApnListSync();
+
+            // filter out ApnContext with "Connected" state.
+            ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
+            for (ApnContext apnContext : apns) {
+                if (apnContext.getState() == State.CONNECTED) {
+                    connectedApns.add(apnContext);
                 }
             }
-            DataConnectionAc dcac = apnContext.getDataConnectionAc();
-            if (dcac == null) {
+
+            // No "Connected" ApnContext associated with this CID. Ignore.
+            if (connectedApns.isEmpty()) {
                 continue;
             }
-            int connectionId = dcac.getCidSync();
 
-            if (apnContext.getState() == State.CONNECTED) {
-                // The way things are supposed to work, the PDP list
-                // should not contain the CID after it disconnects.
-                // However, the way things really work, sometimes the PDP
-                // context is still listed with active = false, which
-                // makes it hard to distinguish an activating context from
-                // an activated-and-then de-activated one.
-                if (response.containsKey(connectionId)) {
-                    DataCallState newState = response.get(connectionId);
-                    if (DBG) log("onDataStateChanged(ar): Found ConnId=" + connectionId
+            if (DBG) log("onDataStateChanged(ar): Found ConnId=" + newState.cid
                             + " newState=" + newState.toString());
-                    if (newState.active != 0) {
-                        boolean resetConnection;
-                        switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
-                        case NONE:
-                            if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
-                            resetConnection = false;
-                            break;
-                        case CHANGED:
-                            if (DBG) log("onDataStateChanged(ar): Found and changed, notify");
-                            mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
-                                                        apnContext.getApnType());
-                            // Temporary hack, at this time a transition from CDMA -> Global
-                            // fails so we'll hope for the best and not reset the connection.
-                            // @see bug/4455071
-                            if (SystemProperties.getBoolean("telephony.ignore-state-changes",
-                                                            true)) {
-                                log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
-                                resetConnection = false;
-                            } else {
-                                // Things changed so reset connection, when hack is removed
-                                // this is the normal path.
-                                log("onDataStateChanged(ar): changed so resetting connection");
-                                resetConnection = true;
-                            }
-                            break;
-                        case RESET:
-                        default:
-                            if (DBG) log("onDataStateChanged(ar): an error, reset connection");
-                            resetConnection = true;
-                            break;
-                        }
-                        if (resetConnection == false) continue;
+            if (newState.active != 0) {
+                boolean resetConnection;
+                switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
+                case NONE:
+                    if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
+                    resetConnection = false;
+                    break;
+                case CHANGED:
+                    for (ApnContext apnContext : connectedApns) {
+                        if (DBG) log("onDataStateChanged(ar): Found and changed, notify (" +
+                                     apnContext.toString() + ")");
+                        mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
+                                                    apnContext.getApnType());
                     }
+                    // Temporary hack, at this time a transition from CDMA -> Global
+                    // fails so we'll hope for the best and not reset the connection.
+                    // @see bug/4455071
+                    if (SystemProperties.getBoolean("telephony.ignore-state-changes",
+                                                    true)) {
+                        log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
+                        resetConnection = false;
+                    } else {
+                        // Things changed so reset connection, when hack is removed
+                        // this is the normal path.
+                        log("onDataStateChanged(ar): changed so resetting connection");
+                        resetConnection = true;
+                    }
+                    break;
+                case RESET:
+                default:
+                    if (DBG) log("onDataStateChanged(ar): an error, reset connection");
+                    resetConnection = true;
+                    break;
                 }
-
-                if (DBG) log("onDataStateChanged(ar): reset connection.");
-
-                // Add an event log when the network drops PDP
-                int cid = getCellLocationId();
-                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
-                        TelephonyManager.getDefault().getNetworkType());
-
-                cleanUpConnection(true, apnContext);
+                if (resetConnection == false) continue;
             }
+
+            if (DBG) log("onDataStateChanged(ar): reset connection.");
+
+            apnsToClear.addAll(connectedApns);
         }
 
+        // step3: Clear apn connection if applicable.
+        if (!apnsToClear.isEmpty()) {
+            // Add an event log when the network drops PDP
+            int cid = getCellLocationId();
+            EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
+                                TelephonyManager.getDefault().getNetworkType());
+        }
+
+        for (ApnContext apnContext : apnsToClear) {
+            cleanUpConnection(true, apnContext);
+        }
         if (DBG) log("onDataStateChanged(ar): X");
     }
 
@@ -1332,7 +1435,8 @@
         return retry;
     }
 
-    private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
+    private void reconnectAfterFail(FailCause lastFailCauseCode,
+                                    ApnContext apnContext, int retryOverride) {
         if (apnContext == null) {
             loge("reconnectAfterFail: apnContext == null, impossible");
             return;
@@ -1357,9 +1461,14 @@
                 }
             }
 
-            int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+            // If retry needs to be backed off for specific case (determined by RIL/Modem)
+            // use the specified timer instead of pre-configured retry pattern.
+            int nextReconnectDelay = retryOverride;
+            if (nextReconnectDelay < 0) {
+                nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+                apnContext.getDataConnection().increaseRetryCount();
+            }
             startAlarmForReconnect(nextReconnectDelay, apnContext);
-            apnContext.getDataConnection().increaseRetryCount();
 
             if (!shouldPostNotification(lastFailCauseCode)) {
                 if (DBG) {
@@ -1379,21 +1488,28 @@
                 + (delay / 1000) + "s");
         }
 
+        DataConnectionAc dcac = apnContext.getDataConnectionAc();
+
+        if ((dcac == null) || (dcac.dataConnection == null)) {
+            // should not happen, but just in case.
+            loge("null dcac or dc.");
+            return;
+        }
+
         AlarmManager am =
             (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
 
-        // TODO : Register the receiver only once maybe in baseclass.
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
-        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
-
-        Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
+        Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
+                                   dcac.dataConnection.getDataConnectionId());
         intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
-        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
-        apnContext.setReconnectIntent(PendingIntent.getBroadcast (
-                mPhone.getContext(), 0, intent, 0));
+        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE,
+                        dcac.dataConnection.getDataConnectionId());
+
+        PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
+                                                                intent, 0);
+        dcac.setReconnectIntentSync(alarmIntent);
         am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                SystemClock.elapsedRealtime() + delay, apnContext.getReconnectIntent());
+                SystemClock.elapsedRealtime() + delay, alarmIntent);
 
     }
 
@@ -1664,7 +1780,13 @@
                     }
                 } else {
                     if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
-                    startDelayedRetry(cause, apnContext);
+                    // check to see if retry should be overridden for this failure.
+                    int retryOverride = -1;
+                    if (ar.exception instanceof DataConnection.CallSetupException) {
+                        retryOverride =
+                            ((DataConnection.CallSetupException)ar.exception).getRetryOverride();
+                    }
+                    startDelayedRetry(cause, apnContext, retryOverride);
                 }
             } else {
                 if (DBG) log("onDataSetupComplete: Try next APN");
@@ -1692,9 +1814,6 @@
         }
 
         apnContext.setState(State.IDLE);
-        apnContext.setApnSetting(null);
-        apnContext.setDataConnection(null);
-        apnContext.setDataConnectionAc(null);
 
         mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
 
@@ -1703,6 +1822,9 @@
         if (!isConnected()) {
             if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
                 // Radio will be turned off. No need to retry data setup
+                apnContext.setApnSetting(null);
+                apnContext.setDataConnection(null);
+                apnContext.setDataConnectionAc(null);
                 return;
             }
         }
@@ -1714,6 +1836,10 @@
             // we're not tying up the RIL command channel.
             // This also helps in any external dependency to turn off the context.
             startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
+        } else {
+            apnContext.setApnSetting(null);
+            apnContext.setDataConnection(null);
+            apnContext.setDataConnectionAc(null);
         }
     }
 
@@ -1839,6 +1965,11 @@
                     " status=" + status);
         }
 
+        // install reconnect intent filter for this data connection.
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_RECONNECT_ALARM + '.' + id);
+        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
         if (DBG) log("createDataConnection() X id=" + id);
         return conn;
     }
@@ -1936,9 +2067,10 @@
         return result.toString();
     }
 
-    private void startDelayedRetry(GsmDataConnection.FailCause cause, ApnContext apnContext) {
+    private void startDelayedRetry(GsmDataConnection.FailCause cause,
+                                   ApnContext apnContext, int retryOverride) {
         notifyNoData(cause, apnContext);
-        reconnectAfterFail(cause, apnContext);
+        reconnectAfterFail(cause, apnContext, retryOverride);
     }
 
     private void setPreferredApn(int pos) {
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index c4a6f53..6e9d0f9d 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -502,16 +502,17 @@
 
     @SmallTest
     public void testFormatNumberToE164() {
-        assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "us"));
-        assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "us"));
-        assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "us"));
+        // Note: ISO 3166-1 only allows upper case country codes.
+        assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
+        assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
+        assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
     }
 
     @SmallTest
     public void testFormatNumber() {
-        assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "us"));
-        assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "us"));
-        assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "us"));
+        assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US"));
+        assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "US"));
+        assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US"));
 
     }
 
diff --git a/tests/BiDiTests/res/drawable/end.png b/tests/BiDiTests/res/drawable/end.png
new file mode 100644
index 0000000..0c110be
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/end.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/start.png b/tests/BiDiTests/res/drawable/start.png
new file mode 100644
index 0000000..783bf90
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/start.png
Binary files differ
diff --git a/tests/BiDiTests/res/layout/textview_direction_ltr.xml b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
new file mode 100644
index 0000000..f7b7b8e
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_direction_ltr"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="ltr">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:textDirection="ltr">
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/textview_direction_rtl.xml b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
new file mode 100644
index 0000000..81c5411
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_direction_rtl"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="rtl">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:textDirection="rtl">
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/textview_locale.xml b/tests/BiDiTests/res/layout/textview_locale.xml
new file mode 100644
index 0000000..a2dcbf9
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_locale.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_locale"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="locale">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent">
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+
+    </LinearLayout>
+
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_ltr.xml b/tests/BiDiTests/res/layout/textview_ltr.xml
new file mode 100644
index 0000000..6e6b976
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_ltr.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_ltr"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="ltr">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent">
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+
+    </LinearLayout>
+
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_rtl.xml b/tests/BiDiTests/res/layout/textview_rtl.xml
new file mode 100644
index 0000000..117227d
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_rtl.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_rtl"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="rtl">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent">
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="start"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="end"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="left"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="right"
+                />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_hebrew_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_latin_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_multiline_text"
+                  android:minWidth="200dip"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:paddingLeft="5dip"
+                  android:paddingRight="15dip"
+                  android:drawablePadding="3dip"
+                  android:background="#884"
+                  android:layout_marginLeft="5dip"
+                  android:layout_marginRight="15dip"
+                  android:gravity="center"
+                />
+
+    </LinearLayout>
+
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/view_group_margin_mixed.xml b/tests/BiDiTests/res/layout/view_group_margin_mixed.xml
new file mode 100644
index 0000000..5845b38
--- /dev/null
+++ b/tests/BiDiTests/res/layout/view_group_margin_mixed.xml
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:id="@+id/view_group_margin_mixed"
+             android:layout_width="fill_parent"
+             android:layout_height="fill_parent"
+             android:background="#FFFFFFFF">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content">
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="ltr">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="rtl">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="inherit">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="locale">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index 16dc263..c0bbe94 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -38,4 +38,8 @@
     <string name="hebrew_text">&#x05DD;&#x05DE;</string>
     <string name="menu_add">Add</string>
     <string name="menu_delete">Delete</string>
-</resources>
\ No newline at end of file
+    <string name="textview_hebrew_text">&#x05DD;&#x05DE;ab?!</string>
+    <string name="textview_latin_text">ab&#x05DD;&#x05DE;?!</string>
+    <string name="textview_multiline_text">&#x05DD;&#x05DE;?!\nab?!</string>
+</resources>
+
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index bee1881..c033879 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -100,29 +100,39 @@
         List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
 
         addItem(result, "Basic", BiDiTestBasic.class, R.id.basic);
+
         addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas);
-        
+
         addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr);
         addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl);
         addItem(result, "Linear LOC", BiDiTestLinearLayoutLocale.class, R.id.linear_layout_locale);
-        
+
         addItem(result, "Frame LTR", BiDiTestFrameLayoutLtr.class, R.id.frame_layout_ltr);
         addItem(result, "Frame RTL", BiDiTestFrameLayoutRtl.class, R.id.frame_layout_rtl);
         addItem(result, "Frame LOC", BiDiTestFrameLayoutLocale.class, R.id.frame_layout_locale);
-        
+
         addItem(result, "Relative LTR", BiDiTestRelativeLayoutLtr.class, R.id.relative_layout_ltr);
         addItem(result, "Relative RTL", BiDiTestRelativeLayoutRtl.class, R.id.relative_layout_rtl);
-        
+
         addItem(result, "Relative2 LTR", BiDiTestRelativeLayout2Ltr.class, R.id.relative_layout_2_ltr);
         addItem(result, "Relative2 RTL", BiDiTestRelativeLayout2Rtl.class, R.id.relative_layout_2_rtl);
         addItem(result, "Relative2 LOC", BiDiTestRelativeLayout2Locale.class, R.id.relative_layout_2_locale);
-        
+
         addItem(result, "Table LTR", BiDiTestTableLayoutLtr.class, R.id.table_layout_ltr);
         addItem(result, "Table RTL", BiDiTestTableLayoutRtl.class, R.id.table_layout_rtl);
         addItem(result, "Table LOC", BiDiTestTableLayoutLocale.class, R.id.table_layout_locale);
 
-        addItem(result, "ViewPadding", BiDiTestViewPadding.class, R.id.view_padding);
-        addItem(result, "ViewPadding MIXED", BiDiTestViewPaddingMixed.class, R.id.view_padding_mixed);
+        addItem(result, "Padding", BiDiTestViewPadding.class, R.id.view_padding);
+        addItem(result, "Padding MIXED", BiDiTestViewPaddingMixed.class, R.id.view_padding_mixed);
+
+        addItem(result, "Margin MIXED", BiDiTestViewGroupMarginMixed.class, R.id.view_group_margin_mixed);
+
+        addItem(result, "TextView LTR", BiDiTestTextViewLtr.class, R.id.textview_ltr);
+        addItem(result, "TextView RTL", BiDiTestTextViewRtl.class, R.id.textview_rtl);
+        addItem(result, "TextView LOC", BiDiTestTextViewLocale.class, R.id.textview_locale);
+
+        addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
+        addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
 
         return result;
     }
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java
new file mode 100644
index 0000000..882ed1f
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewDirectionLtr extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_direction_ltr, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java
new file mode 100644
index 0000000..e63ee35
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewDirectionRtl extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_direction_rtl, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLocale.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLocale.java
new file mode 100644
index 0000000..6c64755
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLocale.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewLocale extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_locale, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLtr.java
new file mode 100644
index 0000000..b168411
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLtr.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewLtr extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_ltr, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewRtl.java
new file mode 100644
index 0000000..6f36ce6
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewRtl.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewRtl extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_rtl, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java
new file mode 100644
index 0000000..ce8c380
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java
@@ -0,0 +1,17 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestViewGroupMarginMixed extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.view_group_margin_mixed, container, false);
+    }
+}
diff --git a/tests/CoreTests/MODULE_LICENSE_APACHE2 b/tests/CoreTests/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/tests/CoreTests/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/tests/GridLayoutTest/res/layout/grid7.xml b/tests/GridLayoutTest/res/layout/grid7.xml
index b97a00b..b9e58d7 100644
--- a/tests/GridLayoutTest/res/layout/grid7.xml
+++ b/tests/GridLayoutTest/res/layout/grid7.xml
@@ -15,56 +15,26 @@
 
 <GridLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
-
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout
-        android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="10dip" >
+        android:layout_height="match_parent">
+    android:columnCount="2"
+    <Space
+            android:layout_row="0"
+            android:layout_column="0"
+            android:layout_width="109dip"
+            android:layout_height="108dip"/>
 
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingRight="5dip"
-            android:text="flabe" />
+    <Button
+            android:text="Button 1"
+            android:layout_row="0"
+            android:layout_column="1"
+            />
 
-        <Button android:id="@+id/initialActivity"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="bax" />
-    </LinearLayout>
-
-    <LinearLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="5dip" >
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingRight="5dip"
-            android:text="bar" />
-
-        <EditText android:id="@+id/numberOfEvents"
-            android:layout_marginLeft="2dip"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:background="@android:drawable/editbox_background"
-            android:numeric="integer"
-            android:scrollHorizontally="true"
-            android:maxLines="1" />
-    </LinearLayout>
-
-    <Button android:id="@+id/start"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:paddingTop="10dip"
-        android:text="Foo" />
+    <Button
+            android:text="Button 2"
+            android:layout_row="1"
+            android:layout_column="1"
+            />
 
 </GridLayout>
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c650021..8734143 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -31,6 +31,24 @@
         android:hardwareAccelerated="true">
 
         <activity
+                android:name="TimeDialogActivity"
+                android:label="_TimeDialog">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
+                android:name="OpaqueActivity"
+                android:label="_Opaque">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="GetBitmapActivity"
                 android:label="_GetBitmap">
             <intent-filter>
@@ -485,8 +503,7 @@
 
         <activity
                 android:name="Animated3dActivity"
-                android:label="_Animated 3d"
-                android:theme="@android:style/Theme.Translucent.NoTitleBar">
+                android:label="_Animated 3d">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index 9bb5ba8..e1ca756 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -19,13 +19,17 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.SurfaceTexture;
-import android.opengl.GLES20;
+import android.opengl.GLUtils;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.TextureView;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import javax.microedition.khronos.egl.EGL10;
@@ -36,6 +40,12 @@
 import javax.microedition.khronos.egl.EGLSurface;
 import javax.microedition.khronos.opengles.GL;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import static android.opengl.GLES20.*;
+
 @SuppressWarnings({"UnusedDeclaration"})
 public class GLTextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
     private RenderThread mRenderThread;
@@ -48,12 +58,14 @@
         mTextureView = new TextureView(this);
         mTextureView.setSurfaceTextureListener(this);
 
-        setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+        setContentView(mTextureView, new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
+                Gravity.CENTER));
     }
 
     @Override
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
-        mRenderThread = new RenderThread(surface);
+        mRenderThread = new RenderThread(getResources(), surface);
         mRenderThread.start();
 
         mTextureView.setCameraDistance(5000);
@@ -85,17 +97,20 @@
         }
     }
 
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+    }
+
     private static class RenderThread extends Thread {
         private static final String LOG_TAG = "GLTextureView";
 
         static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        static final int EGL_SURFACE_TYPE = 0x3033;
-        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
         static final int EGL_OPENGL_ES2_BIT = 4;
 
         private volatile boolean mFinished;
 
-        private SurfaceTexture mSurface;
+        private final Resources mResources;
+        private final SurfaceTexture mSurface;
         
         private EGL10 mEgl;
         private EGLDisplay mEglDisplay;
@@ -104,26 +119,96 @@
         private EGLSurface mEglSurface;
         private GL mGL;
 
-        RenderThread(SurfaceTexture surface) {
+        RenderThread(Resources resources, SurfaceTexture surface) {
+            mResources = resources;
             mSurface = surface;
         }
 
+        private static final String sSimpleVS =
+                "attribute vec4 position;\n" +
+                "attribute vec2 texCoords;\n" +
+                "varying vec2 outTexCoords;\n" +
+                "\nvoid main(void) {\n" +
+                "    outTexCoords = texCoords;\n" +
+                "    gl_Position = position;\n" +
+                "}\n\n";
+        private static final String sSimpleFS =
+                "precision mediump float;\n\n" +
+                "varying vec2 outTexCoords;\n" +
+                "uniform sampler2D texture;\n" +
+                "\nvoid main(void) {\n" +
+                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
+                "}\n\n";
+
+        private static final int FLOAT_SIZE_BYTES = 4;
+        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+        private final float[] mTriangleVerticesData = {
+                // X, Y, Z, U, V
+                -1.0f, -1.0f, 0, 0.f, 0.f,
+                1.0f, -1.0f, 0, 1.f, 0.f,
+                -1.0f,  1.0f, 0, 0.f, 1.f,
+                1.0f,   1.0f, 0, 1.f, 1.f,
+        };
+
         @Override
         public void run() {
             initGL();
+            
+            FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
+                    * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+            triangleVertices.put(mTriangleVerticesData).position(0);
 
-            float red = 1.0f;
+            int texture = loadTexture(R.drawable.large_photo);
+            int program = buildProgram(sSimpleVS, sSimpleFS);
+
+            int attribPosition = glGetAttribLocation(program, "position");
+            checkGlError();
+
+            int attribTexCoords = glGetAttribLocation(program, "texCoords");
+            checkGlError();
+
+            int uniformTexture = glGetUniformLocation(program, "texture");
+            checkGlError();
+
+            glBindTexture(GL_TEXTURE_2D, texture);
+            checkGlError();
+
+            glUseProgram(program);
+            checkGlError();
+
+            glEnableVertexAttribArray(attribPosition);
+            checkGlError();
+
+            glEnableVertexAttribArray(attribTexCoords);
+            checkGlError();
+
+            glUniform1i(texture, 0);
+            checkGlError();
+            
             while (!mFinished) {
                 checkCurrent();
 
                 Log.d(LOG_TAG, "Rendering frame");
 
-                GLES20.glClearColor(red, 0.0f, 0.0f, 1.0f);
+                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                 checkGlError();
 
-                GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+                glClear(GL_COLOR_BUFFER_BIT);
                 checkGlError();
 
+                // drawQuad
+                triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+                glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
+                        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+                triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+                glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
+                        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
                 if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
                     throw new RuntimeException("Cannot swap buffers");
                 }
@@ -134,14 +219,90 @@
                 } catch (InterruptedException e) {
                     // Ignore
                 }
-
-                red += 0.021f;
-                if (red > 1.0f) red = 0.0f;
             }
 
             finishGL();
         }
 
+        private int loadTexture(int resource) {
+            int[] textures = new int[1];
+
+            glActiveTexture(GL_TEXTURE0);
+            glGenTextures(1, textures, 0);
+            checkGlError();
+
+            int texture = textures[0];
+            glBindTexture(GL_TEXTURE_2D, texture);
+            checkGlError();
+            
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+            Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
+
+            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
+            checkGlError();
+
+            bitmap.recycle();
+
+            return texture;
+        }
+        
+        private int buildProgram(String vertex, String fragment) {
+            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+            if (vertexShader == 0) return 0;
+
+            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+            if (fragmentShader == 0) return 0;
+
+            int program = glCreateProgram();
+            glAttachShader(program, vertexShader);
+            checkGlError();
+
+            glAttachShader(program, fragmentShader);
+            checkGlError();
+
+            glLinkProgram(program);
+            checkGlError();
+
+            int[] status = new int[1];
+            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
+            if (status[0] != GL_TRUE) {
+                String error = glGetProgramInfoLog(program);
+                Log.d(LOG_TAG, "Error while linking program:\n" + error);
+                glDeleteShader(vertexShader);
+                glDeleteShader(fragmentShader);
+                glDeleteProgram(program);
+                return 0;
+            }
+
+            return program;
+        }
+        
+        private int buildShader(String source, int type) {
+            int shader = glCreateShader(type);
+
+            glShaderSource(shader, source);
+            checkGlError();
+
+            glCompileShader(shader);
+            checkGlError();
+
+            int[] status = new int[1];
+            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
+            if (status[0] != GL_TRUE) {
+                String error = glGetShaderInfoLog(shader);
+                Log.d(LOG_TAG, "Error while compiling shader:\n" + error);
+                glDeleteShader(shader);
+                return 0;
+            }
+            
+            return shader;
+        }
+
         private void checkEglError() {
             int error = mEgl.eglGetError();
             if (error != EGL10.EGL_SUCCESS) {
@@ -150,8 +311,8 @@
         }
 
         private void checkGlError() {
-            int error = GLES20.glGetError();
-            if (error != GLES20.GL_NO_ERROR) {
+            int error = glGetError();
+            if (error != GL_NO_ERROR) {
                 Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
             }
         }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java
index 2e23aaa..f420fa0 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java
@@ -100,4 +100,9 @@
         mCamera.stopPreview();
         mCamera.release();
     }
+
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        // Ignored
+    }
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java
new file mode 100644
index 0000000..af45f29
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class OpaqueActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final OpaqueView view = new OpaqueView(this);
+        setContentView(view, new FrameLayout.LayoutParams(100, 100, Gravity.CENTER));
+    }
+
+    public static class OpaqueView extends View {
+        public OpaqueView(Context c) {
+            super(c);
+            setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    invalidate();
+                    Log.d("OpaqueView", "Invalidate");
+                }
+            });
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+            canvas.drawColor(0xffff0000, PorterDuff.Mode.SRC);
+        }
+
+        @Override
+        public boolean isOpaque() {
+            return true;
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index fa2e39a..c857ded 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -17,8 +17,6 @@
 package com.android.test.hwui;
 
 import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
@@ -55,7 +53,7 @@
             @Override
             public void onClick(View v) {
                 if (mAdded) {
-                    mAnimatorSet.cancel();
+                    if (mAnimatorSet != null) mAnimatorSet.cancel();
                     mContent.removeView(mTextureView);
                 } else {
                     mContent.addView(mTextureView);
@@ -85,25 +83,19 @@
 
         mTextureView.setCameraDistance(5000);
 
-        ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
-        rotationY.setRepeatMode(ObjectAnimator.REVERSE);
-        rotationY.setRepeatCount(ObjectAnimator.INFINITE);
-        rotationY.setDuration(4000);
-        rotationY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                ((View) mTextureView.getParent()).invalidate();
-            }
-        });
+//        ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
+//        rotationY.setRepeatMode(ObjectAnimator.REVERSE);
+//        rotationY.setRepeatCount(ObjectAnimator.INFINITE);
+//        rotationY.setDuration(4000);
 
-        ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
-        alpha.setRepeatMode(ObjectAnimator.REVERSE);
-        alpha.setRepeatCount(ObjectAnimator.INFINITE);
-        alpha.setDuration(4000);
+//        ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
+//        alpha.setRepeatMode(ObjectAnimator.REVERSE);
+//        alpha.setRepeatCount(ObjectAnimator.INFINITE);
+//        alpha.setDuration(4000);
 
-        mAnimatorSet = new AnimatorSet();
-        mAnimatorSet.play(alpha).with(rotationY);
-        mAnimatorSet.start();
+//        mAnimatorSet = new AnimatorSet();
+//        mAnimatorSet.play(alpha).with(rotationY);
+//        mAnimatorSet.start();
     }
 
     @Override
@@ -116,4 +108,9 @@
         mCamera.stopPreview();
         mCamera.release();
     }
+
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        // Ignored
+    }
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java
new file mode 100644
index 0000000..9e3e950
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.app.TimePickerDialog;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class TimeDialogActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        FrameLayout layout = new FrameLayout(this);
+        Button b = new Button(this);
+        b.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
+                FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
+        b.setText("Show dialog");
+        b.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                new TimePickerDialog(TimeDialogActivity.this, null, 12, 12, true).show();
+            }
+        });
+        layout.addView(b);
+        
+        setContentView(layout);
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index 3f57799..c706286 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -100,6 +100,7 @@
 
     private ProgramVertex mProgVertex;
     private ProgramVertexFixedFunction.Constants mPVA;
+    private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
 
     // Custom shaders
     private ProgramVertex mProgVertexCustom;
@@ -388,6 +389,7 @@
       i.Proj = projNorm;
       i.MVP = projNorm;
       mPvStarAlloc.set(i, 0, true);
+      mPvProjectionAlloc.setProjection(projNorm);
   }
 
     private void initProgramVertex() {
@@ -405,8 +407,14 @@
         // For galaxy live wallpaper
         mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
         mScript.bind_vpConstants(mPvStarAlloc);
+        mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
         updateProjectionMatrices();
 
+        pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        ProgramVertex pvbp = pvb.create();
+        ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
+        mScript.set_gPVBkProj(pvbp);
+
         ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
         String t =  "varying vec4 varColor;\n" +
                     "varying vec2 varTex0;\n" +
@@ -648,10 +656,10 @@
         prepareTestData();
 
         initSamplers();
-        initProgramStore();
-        initProgramFragment();
         initMesh();
         initProgramVertex();
+        initProgramStore();
+        initProgramFragment();
         initFonts();
         loadImages();
         initProgramRaster();
@@ -674,7 +682,6 @@
                                            Allocation.USAGE_GRAPHICS_RENDER_TARGET);
         mScript.set_gRenderBufferDepth(offscreen);
 
-
         mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
         for (int i = 0; i < 100; i++) {
             ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index 6d80b0e..bb81862 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -393,19 +393,28 @@
     rsgBindProgramStore(gProgStoreBlendAlpha);
     rsgBindProgramFragment(gProgFragmentTexture);
     rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+    rsgDrawQuadTexCoords(
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+            0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
+            gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
+            gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
 
     int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
 
-    float size = 50.0;
+    float wSize = gRenderSurfaceW/(float)meshCount;
+    float hSize = gRenderSurfaceH/(float)meshCount;
     rs_matrix4x4 matrix;
-    rsMatrixLoadScale(&matrix, size, size, 1.0);
+    rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
 
     float yPos = 0;
+    float yPad = hSize / 2;
+    float xPad = wSize / 2;
     for (int y = 0; y < meshCount; y++) {
-        yPos = (y + 1) * 50;
+        yPos = y * hSize + yPad;
         float xPos = 0;
         for (int x = 0; x < meshCount; x++) {
-            xPos = (x + 1) * 50;
+            xPos = x * wSize + xPad;
             rs_matrix4x4 transMatrix;
             rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
             rsMatrixMultiply(&transMatrix, &matrix);
@@ -529,11 +538,12 @@
 }
 
 // Display images and text with live wallpaper in the background
-static void dispalyLiveWallPaper(int wResolution, int hResolution) {
+static void displayLiveWallPaper(int wResolution, int hResolution) {
     bindProgramVertexOrtho();
 
     drawGalaxy();
 
+    rsgBindProgramVertex(gProgVertex);
     rsgBindProgramStore(gProgStoreBlendAlpha);
     rsgBindProgramFragment(gProgFragmentTexture);
     rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
@@ -958,7 +968,7 @@
         displayListView();
         break;
     case 30:
-        dispalyLiveWallPaper(7, 5);
+        displayLiveWallPaper(7, 5);
         break;
     }
 }
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java
index 89fc34b..d1b23fa 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java
@@ -39,7 +39,7 @@
 public class RSTest extends Activity {
     //EventListener mListener = new EventListener();
 
-    private static final String LOG_TAG = "libRS_jni";
+    private static final String LOG_TAG = "RSTest";
     private static final boolean DEBUG  = false;
     private static final boolean LOG_ENABLED = false;
 
@@ -73,6 +73,14 @@
         mView.pause();
     }
 
+    @Override
+    protected void onStop() {
+        // Actually kill the app if we are stopping. We don't want to
+        // continue/resume this test ever. It should always start fresh.
+        finish();
+        super.onStop();
+    }
+
     static void log(String message) {
         if (LOG_ENABLED) {
             Log.v(LOG_TAG, message);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
index a7722c7..6151431 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
@@ -17,7 +17,6 @@
 package com.android.rs.test;
 import android.content.Context;
 import android.renderscript.RenderScript.RSMessageHandler;
-import android.util.Log;
 
 public class UnitTest extends Thread {
     public String name;
@@ -67,7 +66,7 @@
                         result = -1;
                         break;
                     default:
-                        android.util.Log.v("RenderScript", "Unit test got unexpected message");
+                        RSTest.log("Unit test got unexpected message");
                         return;
                 }
             }
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index a45e879..fb2fc85 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -190,7 +190,6 @@
 
         // Used by DecimalFormatSymbols.
         result.zeroDigit = '0';
-        result.digit = '0';
         result.decimalSeparator = '.';
         result.groupingSeparator = ',';
         result.patternSeparator = ' ';
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 65a64cd..894611b 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -30,9 +30,9 @@
 Consequently this tool:
 - parses the input JAR,
 - modifies some of the classes directly using some bytecode manipulation,
-- filters some packages and removes some that we don't want to end in the output JAR,
+- filters some packages and removes those we don't want in the output JAR,
 - injects some new classes,
-- and generates a modified JAR file that is suitable for the Android plugin
+- generates a modified JAR file that is suitable for the Android plugin
   for Eclipse to perform rendering.
 
 The ASM library is used to do the bytecode modification using its visitor pattern API.
@@ -63,7 +63,7 @@
 
 To do that, the analyzer is created with a list of base classes to keep -- everything
 that derives from these is kept. Currently the one such class is android.view.View:
-since we want to render layouts, anything that is sort of the view needs to be kept.
+since we want to render layouts, anything that is sort of a view needs to be kept.
 
 The analyzer is also given a list of class names to keep in the output.
 This is done using shell-like glob patterns that filter on the fully-qualified
@@ -90,6 +90,7 @@
 - the classes to inject in the output JAR -- these classes are directly implemented
   in layoutlib_create and will be used to interface with the renderer in Eclipse.
 - specific methods to override (see method stubs details below).
+- specific methods for which to delegate calls.
 - specific methods to remove based on their return type.
 - specific classes to rename.
 
@@ -114,6 +115,9 @@
 The code of the methods is then kept as-is, except for native methods which are
 replaced by a stub. Methods that are to be overridden are also replaced by a stub.
 
+The transformed class is then fed through the DelegateClassAdapter to implement
+method delegates. 
+
 Finally fields are also visited and changed from protected/private to public.
 
 
@@ -131,8 +135,7 @@
 method was native. We do not currently provide the parameters. The listener
 can however specify the return value of the overridden method.
 
-An extension being worked on is to actually replace these listeners by
-direct calls to a delegate class, complete with parameters.
+This strategy is now obsolete and replaced by the method delegates.
 
 
 - Strategies
@@ -160,6 +163,9 @@
 by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
 a listener on the method signature and can provide an implementation.
 
+This strategy is now obsolete and replaced by the method delegates.
+See strategy 5 below.
+
 
 3- Renaming classes
 
@@ -195,6 +201,24 @@
 bridge will provide its own implementation.
 
 
+5- Method Delegates
+
+This strategy is used to override method implementations.
+Given a method SomeClass.MethodName(), 1 or 2 methods are generated:
+a- A copy of the original method named SomeClass.MethodName_Original().
+   The content is the original method as-is from the reader.
+   This step is omitted if the method is native, since it has no Java implementation.
+b- A brand new implementation of SomeClass.MethodName() which calls to a
+   non-existing static method named SomeClass_Delegate.MethodName().
+   The implementation of this 'delegate' method is done in layoutlib_brigde.
+
+The delegate method is a static method.
+If the original method is non-static, the delegate method receives the original 'this'
+as its first argument. If the original method is an inner non-static method, it also
+receives the inner 'this' as the second argument.
+
+
+
 - References -
 --------------
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 5c60318..233f72ec 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -51,6 +51,8 @@
      * Returns The list of methods to stub out. Each entry must be in the form
      * "package.package.OuterClass$InnerClass#MethodName".
      * The list can be empty but must not be null.
+     * <p/>
+     * This usage is deprecated. Please use method 'delegates' instead.
      */
     public String[] getOverriddenMethods() {
         return OVERRIDDEN_METHODS;
@@ -158,6 +160,7 @@
     /**
      * The list of methods to stub out. Each entry must be in the form
      *  "package.package.OuterClass$InnerClass#MethodName".
+     *  This usage is deprecated. Please use method 'delegates' instead.
      */
     private final static String[] OVERRIDDEN_METHODS = new String[] {
     };
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
index 9cba8a0..49ddf1d 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
@@ -31,6 +31,11 @@
  */
 public class DelegateClassAdapter extends ClassAdapter {
 
+    /** Suffix added to original methods. */
+    private static final String ORIGINAL_SUFFIX = "_Original";
+    private static String CONSTRUCTOR = "<init>";
+    private static String CLASS_INIT = "<clinit>";
+
     public final static String ALL_NATIVES = "<<all_natives>>";
 
     private final String mClassName;
@@ -73,22 +78,55 @@
         boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) ||
                               mDelegateMethods.contains(name);
 
-        if (useDelegate) {
-            // remove native
-            access = access & ~Opcodes.ACC_NATIVE;
+        if (!useDelegate) {
+            // Not creating a delegate for this method, pass it as-is from the reader
+            // to the writer.
+            return super.visitMethod(access, name, desc, signature, exceptions);
         }
 
-        MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
         if (useDelegate) {
-            DelegateMethodAdapter a = new DelegateMethodAdapter(mLog, mw, mClassName,
-                                                                name, desc, isStatic);
-            if (isNative) {
-                // A native has no code to visit, so we need to generate it directly.
-                a.generateCode();
-            } else {
-                return a;
+            if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) {
+                // We don't currently support generating delegates for constructors.
+                throw new UnsupportedOperationException(
+                    String.format(
+                        "Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)",  //$NON-NLS-1$
+                        mClassName, name, desc));
             }
         }
-        return mw;
+
+        if (isNative) {
+            // Remove native flag
+            access = access & ~Opcodes.ACC_NATIVE;
+            MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions);
+
+            DelegateMethodAdapter2 a = new DelegateMethodAdapter2(
+                    mLog, null /*mwOriginal*/, mwDelegate, mClassName, name, desc, isStatic);
+
+            // A native has no code to visit, so we need to generate it directly.
+            a.generateDelegateCode();
+
+            return mwDelegate;
+        }
+
+        // Given a non-native SomeClass.MethodName(), we want to generate 2 methods:
+        // - A copy of the original method named SomeClass.MethodName_Original().
+        //   The content is the original method as-is from the reader.
+        // - A brand new implementation of SomeClass.MethodName() which calls to a
+        //   non-existing method named SomeClass_Delegate.MethodName().
+        //   The implementation of this 'delegate' method is done in layoutlib_brigde.
+
+        int accessDelegate = access;
+        // change access to public for the original one
+        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+        access |= Opcodes.ACC_PUBLIC;
+
+        MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
+                                                     desc, signature, exceptions);
+        MethodVisitor mwDelegate = super.visitMethod(accessDelegate, name,
+                                                     desc, signature, exceptions);
+
+        DelegateMethodAdapter2 a = new DelegateMethodAdapter2(
+                mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStatic);
+        return a;
     }
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
deleted file mode 100644
index 8d7f016..0000000
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import java.util.ArrayList;
-
-/**
- * This method adapter rewrites a method by discarding the original code and generating
- * a call to a delegate. Original annotations are passed along unchanged.
- * <p/>
- * Calls are delegated to a class named <code>&lt;className&gt;_Delegate</code> with
- * static methods matching the methods to be overridden here. The methods have the
- * same return type. The argument type list is the same except the "this" reference is
- * passed first for non-static methods.
- * <p/>
- * A new annotation is added.
- * <p/>
- * Note that native methods have, by definition, no code so there's nothing a visitor
- * can visit. That means the caller must call {@link #generateCode()} directly for
- * a native and use the visitor pattern for non-natives.
- * <p/>
- * Instances of this class are not re-usable. You need a new instance for each method.
- */
-class DelegateMethodAdapter implements MethodVisitor {
-
-    /**
-     * Suffix added to delegate classes.
-     */
-    public static final String DELEGATE_SUFFIX = "_Delegate";
-
-    private static String CONSTRUCTOR = "<init>";
-    private static String CLASS_INIT = "<clinit>";
-
-    /** The parent method writer */
-    private MethodVisitor mParentVisitor;
-    /** Flag to output the first line number. */
-    private boolean mOutputFirstLineNumber = true;
-    /** The original method descriptor (return type + argument types.) */
-    private String mDesc;
-    /** True if the original method is static. */
-    private final boolean mIsStatic;
-    /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */
-    private final String mClassName;
-    /** The method name. */
-    private final String mMethodName;
-    /** Logger object. */
-    private final Log mLog;
-    /** True if {@link #visitCode()} has been invoked. */
-    private boolean mVisitCodeCalled;
-
-    /**
-     * Creates a new {@link DelegateMethodAdapter} that will transform this method
-     * into a delegate call.
-     * <p/>
-     * See {@link DelegateMethodAdapter} for more details.
-     *
-     * @param log The logger object. Must not be null.
-     * @param mv the method visitor to which this adapter must delegate calls.
-     * @param className The internal class name of the class to visit,
-     *          e.g. <code>com/android/SomeClass$InnerClass</code>.
-     * @param methodName The simple name of the method.
-     * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} +
-     *          {@link Type#getArgumentTypes(String)})
-     * @param isStatic True if the method is declared static.
-     */
-    public DelegateMethodAdapter(Log log,
-            MethodVisitor mv,
-            String className,
-            String methodName,
-            String desc,
-            boolean isStatic) {
-        mLog = log;
-        mParentVisitor = mv;
-        mClassName = className;
-        mMethodName = methodName;
-        mDesc = desc;
-        mIsStatic = isStatic;
-
-        if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
-            // We're going to simplify by not supporting constructors.
-            // The only trick with a constructor is to find the proper super constructor
-            // and call it (and deciding if we should mirror the original method call to
-            // a custom constructor or call a default one.)
-            throw new UnsupportedOperationException(
-                    String.format("Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)",
-                            className, methodName, desc));
-        }
-    }
-
-    /**
-     * Generates the new code for the method.
-     * <p/>
-     * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
-     * (since they have no code to visit).
-     * <p/>
-     * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
-     * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern
-     * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
-     * this method will be invoked from {@link MethodVisitor#visitEnd()}.
-     */
-    public void generateCode() {
-        /*
-         * The goal is to generate a call to a static delegate method.
-         * If this method is non-static, the first parameter will be 'this'.
-         * All the parameters must be passed and then the eventual return type returned.
-         *
-         * Example, let's say we have a method such as
-         *   public void method_1(int a, Object b, ArrayList<String> c) { ... }
-         *
-         * We'll want to create a body that calls a delegate method like this:
-         *   TheClass_Delegate.method_1(this, a, b, c);
-         *
-         * If the method is non-static and the class name is an inner class (e.g. has $ in its
-         * last segment), we want to push the 'this' of the outer class first:
-         *   OuterClass_InnerClass_Delegate.method_1(
-         *     OuterClass.this,
-         *     OuterClass$InnerClass.this,
-         *     a, b, c);
-         *
-         * Only one level of inner class is supported right now, for simplicity and because
-         * we don't need more.
-         *
-         * The generated class name is the current class name with "_Delegate" appended to it.
-         * One thing to realize is that we don't care about generics -- since generic types
-         * are erased at runtime, they have no influence on the method name being called.
-         */
-
-        // Add our annotation
-        AnnotationVisitor aw = mParentVisitor.visitAnnotation(
-                Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(),
-                true); // visible at runtime
-        aw.visitEnd();
-
-        if (!mVisitCodeCalled) {
-            // If this is a direct call to generateCode() as done by DelegateClassAdapter
-            // for natives, visitCode() hasn't been called yet.
-            mParentVisitor.visitCode();
-            mVisitCodeCalled = true;
-        }
-
-        ArrayList<Type> paramTypes = new ArrayList<Type>();
-        String delegateClassName = mClassName + DELEGATE_SUFFIX;
-        boolean pushedArg0 = false;
-        int maxStack = 0;
-
-        // For an instance method (e.g. non-static), push the 'this' preceded
-        // by the 'this' of any outer class, if any.
-        if (!mIsStatic) {
-            // Check if the last segment of the class name has inner an class.
-            // Right now we only support one level of inner classes.
-            int slash = mClassName.lastIndexOf('/');
-            int dol = mClassName.lastIndexOf('$');
-            if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
-                String outerClass = mClassName.substring(0, dol);
-                Type outerType = Type.getObjectType(outerClass);
-
-                // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
-                delegateClassName = delegateClassName.replace('$', '_');
-
-                // The first-level inner class has a package-protected member called 'this$0'
-                // that points to the outer class.
-
-                // Push this.getField("this$0") on the call stack.
-                mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
-                mParentVisitor.visitFieldInsn(Opcodes.GETFIELD,
-                        mClassName,                 // class where the field is defined
-                        "this$0",                   // field name
-                        outerType.getDescriptor()); // type of the field
-                maxStack++;
-                paramTypes.add(outerType);
-            }
-
-            // Push "this" for the instance method, which is always ALOAD 0
-            mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
-            maxStack++;
-            pushedArg0 = true;
-            paramTypes.add(Type.getObjectType(mClassName));
-        }
-
-        // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
-        Type[] argTypes = Type.getArgumentTypes(mDesc);
-        int maxLocals = pushedArg0 ? 1 : 0;
-        for (Type t : argTypes) {
-            int size = t.getSize();
-            mParentVisitor.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
-            maxLocals += size;
-            maxStack += size;
-            paramTypes.add(t);
-        }
-
-        // Construct the descriptor of the delegate based on the parameters
-        // we pushed on the call stack. The return type remains unchanged.
-        String desc = Type.getMethodDescriptor(
-                Type.getReturnType(mDesc),
-                paramTypes.toArray(new Type[paramTypes.size()]));
-
-        // Invoke the static delegate
-        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
-                delegateClassName,
-                mMethodName,
-                desc);
-
-        Type returnType = Type.getReturnType(mDesc);
-        mParentVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
-
-        mParentVisitor.visitMaxs(maxStack, maxLocals);
-        mParentVisitor.visitEnd();
-
-        // For debugging now. Maybe we should collect these and store them in
-        // a text file for helping create the delegates. We could also compare
-        // the text file to a golden and break the build on unsupported changes
-        // or regressions. Even better we could fancy-print something that looks
-        // like the expected Java method declaration.
-        mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
-    }
-
-    /* Pass down to visitor writer. In this implementation, either do nothing. */
-    public void visitCode() {
-        mVisitCodeCalled = true;
-        mParentVisitor.visitCode();
-    }
-
-    /*
-     * visitMaxs is called just before visitEnd if there was any code to rewrite.
-     * Skip the original.
-     */
-    public void visitMaxs(int maxStack, int maxLocals) {
-    }
-
-    /**
-     * End of visiting. Generate the messaging code.
-     */
-    public void visitEnd() {
-        generateCode();
-    }
-
-    /* Writes all annotation from the original method. */
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        return mParentVisitor.visitAnnotation(desc, visible);
-    }
-
-    /* Writes all annotation default values from the original method. */
-    public AnnotationVisitor visitAnnotationDefault() {
-        return mParentVisitor.visitAnnotationDefault();
-    }
-
-    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
-            boolean visible) {
-        return mParentVisitor.visitParameterAnnotation(parameter, desc, visible);
-    }
-
-    /* Writes all attributes from the original method. */
-    public void visitAttribute(Attribute attr) {
-        mParentVisitor.visitAttribute(attr);
-    }
-
-    /*
-     * Only writes the first line number present in the original code so that source
-     * viewers can direct to the correct method, even if the content doesn't match.
-     */
-    public void visitLineNumber(int line, Label start) {
-        if (mOutputFirstLineNumber) {
-            mParentVisitor.visitLineNumber(line, start);
-            mOutputFirstLineNumber = false;
-        }
-    }
-
-    public void visitInsn(int opcode) {
-        // Skip original code.
-    }
-
-    public void visitLabel(Label label) {
-        // Skip original code.
-    }
-
-    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
-        // Skip original code.
-    }
-
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-        // Skip original code.
-    }
-
-    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-        // Skip original code.
-    }
-
-    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
-        // Skip original code.
-    }
-
-    public void visitIincInsn(int var, int increment) {
-        // Skip original code.
-    }
-
-    public void visitIntInsn(int opcode, int operand) {
-        // Skip original code.
-    }
-
-    public void visitJumpInsn(int opcode, Label label) {
-        // Skip original code.
-    }
-
-    public void visitLdcInsn(Object cst) {
-        // Skip original code.
-    }
-
-    public void visitLocalVariable(String name, String desc, String signature,
-            Label start, Label end, int index) {
-        // Skip original code.
-    }
-
-    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
-        // Skip original code.
-    }
-
-    public void visitMultiANewArrayInsn(String desc, int dims) {
-        // Skip original code.
-    }
-
-    public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
-        // Skip original code.
-    }
-
-    public void visitTypeInsn(int opcode, String type) {
-        // Skip original code.
-    }
-
-    public void visitVarInsn(int opcode, int var) {
-        // Skip original code.
-    }
-
-}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
new file mode 100644
index 0000000..ac4ae6d
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+
+/**
+ * This method adapter generates delegate methods.
+ * <p/>
+ * Given a method {@code SomeClass.MethodName()}, this generates 1 or 2 methods:
+ * <ul>
+ * <li> A copy of the original method named {@code SomeClass.MethodName_Original()}.
+ *   The content is the original method as-is from the reader.
+ *   This step is omitted if the method is native, since it has no Java implementation.
+ * <li> A brand new implementation of {@code SomeClass.MethodName()} which calls to a
+ *   non-existing method named {@code SomeClass_Delegate.MethodName()}.
+ *   The implementation of this 'delegate' method is done in layoutlib_brigde.
+ * </ul>
+ * A method visitor is generally constructed to generate a single method; however
+ * here we might want to generate one or two depending on the context. To achieve
+ * that, the visitor here generates the 'original' method and acts as a no-op if
+ * no such method exists (e.g. when the original is a native method).
+ * The delegate method is generated after the {@code visitEnd} of the original method
+ * or by having the class adapter <em>directly</em> call {@link #generateDelegateCode()}
+ * for native methods.
+ * <p/>
+ * When generating the 'delegate', the implementation generates a call to a class
+ * class named <code>&lt;className&gt;_Delegate</code> with static methods matching
+ * the methods to be overridden here. The methods have the same return type.
+ * The argument type list is the same except the "this" reference is passed first
+ * for non-static methods.
+ * <p/>
+ * A new annotation is added to these 'delegate' methods so that we can easily find them
+ * for automated testing.
+ * <p/>
+ * This class isn't intended to be generic or reusable.
+ * It is called by {@link DelegateClassAdapter}, which takes care of properly initializing
+ * the two method writers for the original and the delegate class, as needed, with their
+ * expected names.
+ * <p/>
+ * The class adapter also takes care of calling {@link #generateDelegateCode()} directly for
+ * a native and use the visitor pattern for non-natives.
+ * Note that native methods have, by definition, no code so there's nothing a visitor
+ * can visit.
+ * <p/>
+ * Instances of this class are not re-usable.
+ * The class adapter creates a new instance for each method.
+ */
+class DelegateMethodAdapter2 implements MethodVisitor {
+
+    /** Suffix added to delegate classes. */
+    public static final String DELEGATE_SUFFIX = "_Delegate";
+
+    /** The parent method writer to copy of the original method.
+     *  Null when dealing with a native original method. */
+    private MethodVisitor mOrgWriter;
+    /** The parent method writer to generate the delegating method. Never null. */
+    private MethodVisitor mDelWriter;
+    /** The original method descriptor (return type + argument types.) */
+    private String mDesc;
+    /** True if the original method is static. */
+    private final boolean mIsStatic;
+    /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */
+    private final String mClassName;
+    /** The method name. */
+    private final String mMethodName;
+    /** Logger object. */
+    private final Log mLog;
+
+    /** Array used to capture the first line number information from the original method
+     *  and duplicate it in the delegate. */
+    private Object[] mDelegateLineNumber;
+
+    /**
+     * Creates a new {@link DelegateMethodAdapter2} that will transform this method
+     * into a delegate call.
+     * <p/>
+     * See {@link DelegateMethodAdapter2} for more details.
+     *
+     * @param log The logger object. Must not be null.
+     * @param mvOriginal The parent method writer to copy of the original method.
+     *          Must be {@code null} when dealing with a native original method.
+     * @param mvDelegate The parent method writer to generate the delegating method.
+     *          Must never be null.
+     * @param className The internal class name of the class to visit,
+     *          e.g. <code>com/android/SomeClass$InnerClass</code>.
+     * @param methodName The simple name of the method.
+     * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} +
+     *          {@link Type#getArgumentTypes(String)})
+     * @param isStatic True if the method is declared static.
+     */
+    public DelegateMethodAdapter2(Log log,
+            MethodVisitor mvOriginal,
+            MethodVisitor mvDelegate,
+            String className,
+            String methodName,
+            String desc,
+            boolean isStatic) {
+        mLog = log;
+        mOrgWriter = mvOriginal;
+        mDelWriter = mvDelegate;
+        mClassName = className;
+        mMethodName = methodName;
+        mDesc = desc;
+        mIsStatic = isStatic;
+    }
+
+    /**
+     * Generates the new code for the method.
+     * <p/>
+     * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
+     * (since they have no code to visit).
+     * <p/>
+     * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
+     * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern
+     * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
+     * this method will be invoked from {@link MethodVisitor#visitEnd()}.
+     */
+    public void generateDelegateCode() {
+        /*
+         * The goal is to generate a call to a static delegate method.
+         * If this method is non-static, the first parameter will be 'this'.
+         * All the parameters must be passed and then the eventual return type returned.
+         *
+         * Example, let's say we have a method such as
+         *   public void myMethod(int a, Object b, ArrayList<String> c) { ... }
+         *
+         * We'll want to create a body that calls a delegate method like this:
+         *   TheClass_Delegate.myMethod(this, a, b, c);
+         *
+         * If the method is non-static and the class name is an inner class (e.g. has $ in its
+         * last segment), we want to push the 'this' of the outer class first:
+         *   OuterClass_InnerClass_Delegate.myMethod(
+         *     OuterClass.this,
+         *     OuterClass$InnerClass.this,
+         *     a, b, c);
+         *
+         * Only one level of inner class is supported right now, for simplicity and because
+         * we don't need more.
+         *
+         * The generated class name is the current class name with "_Delegate" appended to it.
+         * One thing to realize is that we don't care about generics -- since generic types
+         * are erased at build time, they have no influence on the method name being called.
+         */
+
+        // Add our annotation
+        AnnotationVisitor aw = mDelWriter.visitAnnotation(
+                Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(),
+                true); // visible at runtime
+        if (aw != null) {
+            aw.visitEnd();
+        }
+
+        mDelWriter.visitCode();
+
+        if (mDelegateLineNumber != null) {
+            Object[] p = mDelegateLineNumber;
+            mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]);
+        }
+
+        ArrayList<Type> paramTypes = new ArrayList<Type>();
+        String delegateClassName = mClassName + DELEGATE_SUFFIX;
+        boolean pushedArg0 = false;
+        int maxStack = 0;
+
+        // For an instance method (e.g. non-static), push the 'this' preceded
+        // by the 'this' of any outer class, if any.
+        if (!mIsStatic) {
+            // Check if the last segment of the class name has inner an class.
+            // Right now we only support one level of inner classes.
+            int slash = mClassName.lastIndexOf('/');
+            int dol = mClassName.lastIndexOf('$');
+            if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
+                String outerClass = mClassName.substring(0, dol);
+                Type outerType = Type.getObjectType(outerClass);
+
+                // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
+                delegateClassName = delegateClassName.replace('$', '_');
+
+                // The first-level inner class has a package-protected member called 'this$0'
+                // that points to the outer class.
+
+                // Push this.getField("this$0") on the call stack.
+                mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
+                mDelWriter.visitFieldInsn(Opcodes.GETFIELD,
+                        mClassName,                 // class where the field is defined
+                        "this$0",                   // field name
+                        outerType.getDescriptor()); // type of the field
+                maxStack++;
+                paramTypes.add(outerType);
+            }
+
+            // Push "this" for the instance method, which is always ALOAD 0
+            mDelWriter.visitVarInsn(Opcodes.ALOAD, 0);
+            maxStack++;
+            pushedArg0 = true;
+            paramTypes.add(Type.getObjectType(mClassName));
+        }
+
+        // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
+        Type[] argTypes = Type.getArgumentTypes(mDesc);
+        int maxLocals = pushedArg0 ? 1 : 0;
+        for (Type t : argTypes) {
+            int size = t.getSize();
+            mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
+            maxLocals += size;
+            maxStack += size;
+            paramTypes.add(t);
+        }
+
+        // Construct the descriptor of the delegate based on the parameters
+        // we pushed on the call stack. The return type remains unchanged.
+        String desc = Type.getMethodDescriptor(
+                Type.getReturnType(mDesc),
+                paramTypes.toArray(new Type[paramTypes.size()]));
+
+        // Invoke the static delegate
+        mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC,
+                delegateClassName,
+                mMethodName,
+                desc);
+
+        Type returnType = Type.getReturnType(mDesc);
+        mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+
+        mDelWriter.visitMaxs(maxStack, maxLocals);
+        mDelWriter.visitEnd();
+
+        // For debugging now. Maybe we should collect these and store them in
+        // a text file for helping create the delegates. We could also compare
+        // the text file to a golden and break the build on unsupported changes
+        // or regressions. Even better we could fancy-print something that looks
+        // like the expected Java method declaration.
+        mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
+    }
+
+    /* Pass down to visitor writer. In this implementation, either do nothing. */
+    public void visitCode() {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitCode();
+        }
+    }
+
+    /*
+     * visitMaxs is called just before visitEnd if there was any code to rewrite.
+     */
+    public void visitMaxs(int maxStack, int maxLocals) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitMaxs(maxStack, maxLocals);
+        }
+    }
+
+    /** End of visiting. Generate the delegating code. */
+    public void visitEnd() {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitEnd();
+        }
+        generateDelegateCode();
+    }
+
+    /* Writes all annotation from the original method. */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (mOrgWriter != null) {
+            return mOrgWriter.visitAnnotation(desc, visible);
+        } else {
+            return null;
+        }
+    }
+
+    /* Writes all annotation default values from the original method. */
+    public AnnotationVisitor visitAnnotationDefault() {
+        if (mOrgWriter != null) {
+            return mOrgWriter.visitAnnotationDefault();
+        } else {
+            return null;
+        }
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
+            boolean visible) {
+        if (mOrgWriter != null) {
+            return mOrgWriter.visitParameterAnnotation(parameter, desc, visible);
+        } else {
+            return null;
+        }
+    }
+
+    /* Writes all attributes from the original method. */
+    public void visitAttribute(Attribute attr) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitAttribute(attr);
+        }
+    }
+
+    /*
+     * Only writes the first line number present in the original code so that source
+     * viewers can direct to the correct method, even if the content doesn't match.
+     */
+    public void visitLineNumber(int line, Label start) {
+        // Capture the first line values for the new delegate method
+        if (mDelegateLineNumber == null) {
+            mDelegateLineNumber = new Object[] { line, start };
+        }
+        if (mOrgWriter != null) {
+            mOrgWriter.visitLineNumber(line, start);
+        }
+    }
+
+    public void visitInsn(int opcode) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitInsn(opcode);
+        }
+    }
+
+    public void visitLabel(Label label) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitLabel(label);
+        }
+    }
+
+    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitTryCatchBlock(start, end, handler, type);
+        }
+    }
+
+    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitMethodInsn(opcode, owner, name, desc);
+        }
+    }
+
+    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitFieldInsn(opcode, owner, name, desc);
+        }
+    }
+
+    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitFrame(type, nLocal, local, nStack, stack);
+        }
+    }
+
+    public void visitIincInsn(int var, int increment) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitIincInsn(var, increment);
+        }
+    }
+
+    public void visitIntInsn(int opcode, int operand) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitIntInsn(opcode, operand);
+        }
+    }
+
+    public void visitJumpInsn(int opcode, Label label) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitJumpInsn(opcode, label);
+        }
+    }
+
+    public void visitLdcInsn(Object cst) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitLdcInsn(cst);
+        }
+    }
+
+    public void visitLocalVariable(String name, String desc, String signature,
+            Label start, Label end, int index) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitLocalVariable(name, desc, signature, start, end, index);
+        }
+    }
+
+    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
+
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitMultiANewArrayInsn(desc, dims);
+        }
+    }
+
+    public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
+
+    public void visitTypeInsn(int opcode, String type) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitTypeInsn(opcode, type);
+        }
+    }
+
+    public void visitVarInsn(int opcode, int var) {
+        if (mOrgWriter != null) {
+            mOrgWriter.visitVarInsn(opcode, var);
+        }
+    }
+
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
index 9a57a4a..d70d028 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
@@ -31,7 +31,7 @@
 
     private static String CONSTRUCTOR = "<init>";
     private static String CLASS_INIT = "<clinit>";
-    
+
     /** The parent method writer */
     private MethodVisitor mParentVisitor;
     /** The method return type. Can be null. */
@@ -40,7 +40,7 @@
     private String mInvokeSignature;
     /** Flag to output the first line number. */
     private boolean mOutputFirstLineNumber = true;
-    /** Flag that is true when implementing a constructor, to accept all original 
+    /** Flag that is true when implementing a constructor, to accept all original
      *  code calling the original super constructor. */
     private boolean mIsInitMethod = false;
 
@@ -55,12 +55,12 @@
         mInvokeSignature = invokeSignature;
         mIsStatic = isStatic;
         mIsNative = isNative;
-        
+
         if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
             mIsInitMethod = true;
         }
     }
-    
+
     private void generateInvoke() {
         /* Generates the code:
          *  OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
@@ -188,7 +188,7 @@
         }
         mParentVisitor.visitMaxs(maxStack, maxLocals);
     }
-    
+
     /**
      * End of visiting.
      * For non-constructor, generate the messaging code and the return statement
@@ -250,6 +250,7 @@
                 generatePop();
                 generateInvoke();
                 mMessageGenerated = true;
+                //$FALL-THROUGH$
             default:
                 mParentVisitor.visitInsn(opcode);
             }
@@ -346,5 +347,5 @@
             mParentVisitor.visitVarInsn(opcode, var);
         }
     }
-    
+
 }
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index e8b3ea8..6e120ce 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -130,7 +130,7 @@
     }
 
     /**
-     * {@link DelegateMethodAdapter} does not support overriding constructors yet,
+     * {@link DelegateMethodAdapter2} does not support overriding constructors yet,
      * so this should fail with an {@link UnsupportedOperationException}.
      *
      * Although not tested here, the message of the exception should contain the
@@ -202,6 +202,7 @@
         // We'll delegate the "get" method of both the inner and outer class.
         HashSet<String> delegateMethods = new HashSet<String>();
         delegateMethods.add("get");
+        delegateMethods.add("privateMethod");
 
         // Generate the delegate for the outer class.
         ClassWriter cwOuter = new ClassWriter(0 /*flags*/);
@@ -234,6 +235,25 @@
                     // The original Outer.get returns 1+10+20,
                     // but the delegate makes it return 4+10+20
                     assertEquals(4+10+20, callGet(o2, 10, 20));
+                    assertEquals(1+10+20, callGet_Original(o2, 10, 20));
+
+                    // The original Outer has a private method that is
+                    // delegated. We should be able to call both the delegate
+                    // and the original (which is now public).
+                    assertEquals("outerPrivateMethod",
+                                 callMethod(o2, "privateMethod_Original", false /*makePublic*/));
+
+                    // The original method is private, so by default we can't access it
+                    boolean gotIllegalAccessException = false;
+                    try {
+                         callMethod(o2, "privateMethod", false /*makePublic*/);
+                    } catch(IllegalAccessException e) {
+                        gotIllegalAccessException = true;
+                    }
+                    assertTrue(gotIllegalAccessException);
+                    // Try again, but now making it accessible
+                    assertEquals("outerPrivate_Delegate",
+                            callMethod(o2, "privateMethod", true /*makePublic*/));
 
                     // Check the inner class. Since it's not a static inner class, we need
                     // to use the hidden constructor that takes the outer class as first parameter.
@@ -246,6 +266,7 @@
                     // The original Inner.get returns 3+10+20,
                     // but the delegate makes it return 6+10+20
                     assertEquals(6+10+20, callGet(i2, 10, 20));
+                    assertEquals(3+10+20, callGet_Original(i2, 10, 20));
                 }
             };
             cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray());
@@ -319,7 +340,7 @@
         }
 
         /**
-         * Accesses {@link OuterClass#get()} or {@link InnerClass#get() }via reflection.
+         * Accesses {@link OuterClass#get} or {@link InnerClass#get}via reflection.
          */
         public int callGet(Object instance, int a, long b) throws Exception {
             Method m = instance.getClass().getMethod("get",
@@ -330,6 +351,39 @@
         }
 
         /**
+         * Accesses the "_Original" methods for {@link OuterClass#get}
+         * or {@link InnerClass#get}via reflection.
+         */
+        public int callGet_Original(Object instance, int a, long b) throws Exception {
+            Method m = instance.getClass().getMethod("get_Original",
+                    new Class<?>[] { int.class, long.class } );
+
+            Object result = m.invoke(instance, new Object[] { a, b });
+            return ((Integer) result).intValue();
+        }
+
+        /**
+         * Accesses the any declared method that takes no parameter via reflection.
+         */
+        @SuppressWarnings("unchecked")
+        public <T> T callMethod(Object instance, String methodName, boolean makePublic) throws Exception {
+            Method m = instance.getClass().getDeclaredMethod(methodName, (Class<?>[])null);
+
+            boolean wasAccessible = m.isAccessible();
+            if (makePublic && !wasAccessible) {
+                m.setAccessible(true);
+            }
+
+            Object result = m.invoke(instance, (Object[])null);
+
+            if (makePublic && !wasAccessible) {
+                m.setAccessible(false);
+            }
+
+            return (T) result;
+        }
+
+        /**
          * Accesses {@link ClassWithNative#add(int, int)} via reflection.
          */
         public int callAdd(Object instance, int a, int b) throws Exception {
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java
index 9dc2f69..f083e76 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java
@@ -39,10 +39,15 @@
         public InnerClass() {
         }
 
-        // Inner.get returns 1+2=3 + a + b
+        // Inner.get returns 2 + 1 + a + b
         public int get(int a, long b) {
             return 2 + mOuterValue + a + (int) b;
         }
     }
+
+    @SuppressWarnings("unused")
+    private String privateMethod() {
+        return "outerPrivateMethod";
+    }
 }
 
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java
index 3252d87..774be8e 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java
@@ -26,5 +26,9 @@
     public static int get(OuterClass instance, int a, long b) {
         return 4 + a + (int) b;
     }
+
+    public static String privateMethod(OuterClass instance) {
+        return "outerPrivate_Delegate";
+    }
 }
 
diff --git a/voip/java/android/net/sip/ISipSessionListener.aidl b/voip/java/android/net/sip/ISipSessionListener.aidl
index 5920bca..690700c 100644
--- a/voip/java/android/net/sip/ISipSessionListener.aidl
+++ b/voip/java/android/net/sip/ISipSessionListener.aidl
@@ -72,6 +72,14 @@
     void onCallBusy(in ISipSession session);
 
     /**
+     * Called when the call is being transferred to a new one.
+     *
+     * @param newSession the new session that the call will be transferred to
+     * @param sessionDescription the new peer's session description
+     */
+    void onCallTransferring(in ISipSession newSession, String sessionDescription);
+
+    /**
      * Called when an error occurs during session initialization and
      * termination.
      *
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index b46f8268..c1affa6 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -26,6 +26,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Message;
 import android.os.RemoteException;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.IOException;
@@ -170,6 +171,7 @@
     private SipProfile mLocalProfile;
     private SipAudioCall.Listener mListener;
     private SipSession mSipSession;
+    private SipSession mTransferringSession;
 
     private long mSessionId = System.currentTimeMillis();
     private String mPeerSd;
@@ -347,6 +349,27 @@
         }
     }
 
+    private synchronized void transferToNewSession() {
+        if (mTransferringSession == null) return;
+        SipSession origin = mSipSession;
+        mSipSession = mTransferringSession;
+        mTransferringSession = null;
+
+        // stop the replaced call.
+        if (mAudioStream != null) {
+            mAudioStream.join(null);
+        } else {
+            try {
+                mAudioStream = new AudioStream(InetAddress.getByName(
+                        getLocalIp()));
+            } catch (Throwable t) {
+                Log.i(TAG, "transferToNewSession(): " + t);
+            }
+        }
+        if (origin != null) origin.endCall();
+        startAudio();
+    }
+
     private SipSession.Listener createListener() {
         return new SipSession.Listener() {
             @Override
@@ -378,6 +401,7 @@
             @Override
             public void onRinging(SipSession session,
                     SipProfile peerProfile, String sessionDescription) {
+                // this callback is triggered only for reinvite.
                 synchronized (SipAudioCall.this) {
                     if ((mSipSession == null) || !mInCall
                             || !session.getCallId().equals(
@@ -404,6 +428,13 @@
                 mPeerSd = sessionDescription;
                 Log.v(TAG, "onCallEstablished()" + mPeerSd);
 
+                // TODO: how to notify the UI that the remote party is changed
+                if ((mTransferringSession != null)
+                        && (session == mTransferringSession)) {
+                    transferToNewSession();
+                    return;
+                }
+
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
@@ -420,7 +451,17 @@
 
             @Override
             public void onCallEnded(SipSession session) {
-                Log.d(TAG, "sip call ended: " + session);
+                Log.d(TAG, "sip call ended: " + session + " mSipSession:" + mSipSession);
+                // reset the trasnferring session if it is the one.
+                if (session == mTransferringSession) {
+                    mTransferringSession = null;
+                    return;
+                }
+                // or ignore the event if the original session is being
+                // transferred to the new one.
+                if ((mTransferringSession != null) ||
+                    (session != mSipSession)) return;
+
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
@@ -489,6 +530,22 @@
             public void onRegistrationDone(SipSession session, int duration) {
                 // irrelevant
             }
+
+            @Override
+            public void onCallTransferring(SipSession newSession,
+                    String sessionDescription) {
+                Log.v(TAG, "onCallTransferring mSipSession:"
+                        + mSipSession + " newSession:" + newSession);
+                mTransferringSession = newSession;
+                // session changing request
+                try {
+                    String answer = createAnswer(sessionDescription).encode();
+                    newSession.answerCall(answer, SESSION_TIMEOUT);
+                } catch (Throwable e) {
+                    Log.e(TAG, "onCallTransferring()", e);
+                    newSession.endCall();
+                }
+            }
         };
     }
 
@@ -675,6 +732,7 @@
     }
 
     private SimpleSessionDescription createAnswer(String offerSd) {
+        if (TextUtils.isEmpty(offerSd)) return createOffer();
         SimpleSessionDescription offer =
                 new SimpleSessionDescription(offerSd);
         SimpleSessionDescription answer =
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 5629b3c..5ba1626 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -160,6 +160,17 @@
         }
 
         /**
+         * Called when the call is being transferred to a new one.
+         *
+         * @hide
+         * @param newSession the new session that the call will be transferred to
+         * @param sessionDescription the new peer's session description
+         */
+        public void onCallTransferring(SipSession newSession,
+                String sessionDescription) {
+        }
+
+        /**
          * Called when an error occurs during session initialization and
          * termination.
          *
@@ -489,6 +500,16 @@
                 }
             }
 
+            public void onCallTransferring(ISipSession session,
+                    String sessionDescription) {
+                if (mListener != null) {
+                    mListener.onCallTransferring(
+                            new SipSession(session, SipSession.this.mListener),
+                            sessionDescription);
+
+                }
+            }
+
             public void onCallChangeFailed(ISipSession session, int errorCode,
                     String message) {
                 if (mListener != null) {
diff --git a/voip/java/android/net/sip/SipSessionAdapter.java b/voip/java/android/net/sip/SipSessionAdapter.java
index 86aca37..f538983 100644
--- a/voip/java/android/net/sip/SipSessionAdapter.java
+++ b/voip/java/android/net/sip/SipSessionAdapter.java
@@ -42,6 +42,10 @@
     public void onCallBusy(ISipSession session) {
     }
 
+    public void onCallTransferring(ISipSession session,
+            String sessionDescription) {
+    }
+
     public void onCallChangeFailed(ISipSession session, int errorCode,
             String message) {
     }
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 4ee86b6..c031bc1 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -71,6 +71,7 @@
 class SipHelper {
     private static final String TAG = SipHelper.class.getSimpleName();
     private static final boolean DEBUG = true;
+    private static final boolean DEBUG_PING = false;
 
     private SipStack mSipStack;
     private SipProvider mSipProvider;
@@ -149,9 +150,17 @@
 
     private ContactHeader createContactHeader(SipProfile profile)
             throws ParseException, SipException {
-        ListeningPoint lp = getListeningPoint();
-        SipURI contactURI =
-                createSipUri(profile.getUserName(), profile.getProtocol(), lp);
+        return createContactHeader(profile, null, 0);
+    }
+
+    private ContactHeader createContactHeader(SipProfile profile,
+            String ip, int port) throws ParseException,
+            SipException {
+        SipURI contactURI = (ip == null)
+                ? createSipUri(profile.getUserName(), profile.getProtocol(),
+                        getListeningPoint())
+                : createSipUri(profile.getUserName(), profile.getProtocol(),
+                        ip, port);
 
         Address contactAddress = mAddressFactory.createAddress(contactURI);
         contactAddress.setDisplayName(profile.getDisplayName());
@@ -167,9 +176,14 @@
 
     private SipURI createSipUri(String username, String transport,
             ListeningPoint lp) throws ParseException {
-        SipURI uri = mAddressFactory.createSipURI(username, lp.getIPAddress());
+        return createSipUri(username, transport, lp.getIPAddress(), lp.getPort());
+    }
+
+    private SipURI createSipUri(String username, String transport,
+            String ip, int port) throws ParseException {
+        SipURI uri = mAddressFactory.createSipURI(username, ip);
         try {
-            uri.setPort(lp.getPort());
+            uri.setPort(port);
             uri.setTransportParam(transport);
         } catch (InvalidArgumentException e) {
             throw new RuntimeException(e);
@@ -177,17 +191,19 @@
         return uri;
     }
 
-    public ClientTransaction sendKeepAlive(SipProfile userProfile, String tag)
-            throws SipException {
+    public ClientTransaction sendOptions(SipProfile caller, SipProfile callee,
+            String tag) throws SipException {
         try {
-            Request request = createRequest(Request.OPTIONS, userProfile, tag);
+            Request request = (caller == callee)
+                    ? createRequest(Request.OPTIONS, caller, tag)
+                    : createRequest(Request.OPTIONS, caller, callee, tag);
 
             ClientTransaction clientTransaction =
                     mSipProvider.getNewClientTransaction(request);
             clientTransaction.sendRequest();
             return clientTransaction;
         } catch (Exception e) {
-            throw new SipException("sendKeepAlive()", e);
+            throw new SipException("sendOptions()", e);
         }
     }
 
@@ -249,23 +265,29 @@
         return ct;
     }
 
+    private Request createRequest(String requestType, SipProfile caller,
+            SipProfile callee, String tag) throws ParseException, SipException {
+        FromHeader fromHeader = createFromHeader(caller, tag);
+        ToHeader toHeader = createToHeader(callee);
+        SipURI requestURI = callee.getUri();
+        List<ViaHeader> viaHeaders = createViaHeaders();
+        CallIdHeader callIdHeader = createCallIdHeader();
+        CSeqHeader cSeqHeader = createCSeqHeader(requestType);
+        MaxForwardsHeader maxForwards = createMaxForwardsHeader();
+
+        Request request = mMessageFactory.createRequest(requestURI,
+                requestType, callIdHeader, cSeqHeader, fromHeader,
+                toHeader, viaHeaders, maxForwards);
+
+        request.addHeader(createContactHeader(caller));
+        return request;
+    }
+
     public ClientTransaction sendInvite(SipProfile caller, SipProfile callee,
             String sessionDescription, String tag)
             throws SipException {
         try {
-            FromHeader fromHeader = createFromHeader(caller, tag);
-            ToHeader toHeader = createToHeader(callee);
-            SipURI requestURI = callee.getUri();
-            List<ViaHeader> viaHeaders = createViaHeaders();
-            CallIdHeader callIdHeader = createCallIdHeader();
-            CSeqHeader cSeqHeader = createCSeqHeader(Request.INVITE);
-            MaxForwardsHeader maxForwards = createMaxForwardsHeader();
-
-            Request request = mMessageFactory.createRequest(requestURI,
-                    Request.INVITE, callIdHeader, cSeqHeader, fromHeader,
-                    toHeader, viaHeaders, maxForwards);
-
-            request.addHeader(createContactHeader(caller));
+            Request request = createRequest(Request.INVITE, caller, callee, tag);
             request.setContent(sessionDescription,
                     mHeaderFactory.createContentTypeHeader(
                             "application", "sdp"));
@@ -305,7 +327,7 @@
         }
     }
 
-    private ServerTransaction getServerTransaction(RequestEvent event)
+    public ServerTransaction getServerTransaction(RequestEvent event)
             throws SipException {
         ServerTransaction transaction = event.getServerTransaction();
         if (transaction == null) {
@@ -344,13 +366,14 @@
      */
     public ServerTransaction sendInviteOk(RequestEvent event,
             SipProfile localProfile, String sessionDescription,
-            ServerTransaction inviteTransaction)
-            throws SipException {
+            ServerTransaction inviteTransaction, String externalIp,
+            int externalPort) throws SipException {
         try {
             Request request = event.getRequest();
             Response response = mMessageFactory.createResponse(Response.OK,
                     request);
-            response.addHeader(createContactHeader(localProfile));
+            response.addHeader(createContactHeader(localProfile, externalIp,
+                    externalPort));
             response.setContent(sessionDescription,
                     mHeaderFactory.createContentTypeHeader(
                             "application", "sdp"));
@@ -419,9 +442,13 @@
     public void sendResponse(RequestEvent event, int responseCode)
             throws SipException {
         try {
+            Request request = event.getRequest();
             Response response = mMessageFactory.createResponse(
-                    responseCode, event.getRequest());
-            if (DEBUG) Log.d(TAG, "send response: " + response);
+                    responseCode, request);
+            if (DEBUG && (!Request.OPTIONS.equals(request.getMethod())
+                    || DEBUG_PING)) {
+                Log.d(TAG, "send response: " + response);
+            }
             getServerTransaction(event).sendResponse(response);
         } catch (ParseException e) {
             throw new SipException("sendResponse()", e);
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 5ad5d26..3b0f5460 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -69,10 +69,11 @@
 public final class SipService extends ISipService.Stub {
     static final String TAG = "SipService";
     static final boolean DEBUGV = false;
-    static final boolean DEBUG = false;
+    static final boolean DEBUG = true;
     private static final int EXPIRY_TIME = 3600;
     private static final int SHORT_EXPIRY_TIME = 10;
     private static final int MIN_EXPIRY_TIME = 60;
+    private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds
 
     private Context mContext;
     private String mLocalIp;
@@ -378,7 +379,7 @@
 
     private void grabWifiLock() {
         if (mWifiLock == null) {
-            if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ acquire wifi lock");
+            if (DEBUG) Log.d(TAG, "acquire wifi lock");
             mWifiLock = ((WifiManager)
                     mContext.getSystemService(Context.WIFI_SERVICE))
                     .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
@@ -389,7 +390,7 @@
 
     private void releaseWifiLock() {
         if (mWifiLock != null) {
-            if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ release wifi lock");
+            if (DEBUG) Log.d(TAG, "release wifi lock");
             mWifiLock.release();
             mWifiLock = null;
             stopWifiScanner();
@@ -459,9 +460,30 @@
         }
     }
 
-    private void startPortMappingLifetimeMeasurement(SipSessionGroup group) {
-        mIntervalMeasurementProcess = new IntervalMeasurementProcess(group);
-        mIntervalMeasurementProcess.start();
+    private void startPortMappingLifetimeMeasurement(
+            SipProfile localProfile) {
+        startPortMappingLifetimeMeasurement(localProfile, -1);
+    }
+
+    private void startPortMappingLifetimeMeasurement(
+            SipProfile localProfile, int maxInterval) {
+        if ((mIntervalMeasurementProcess == null)
+                && (mKeepAliveInterval == -1)
+                && isBehindNAT(mLocalIp)) {
+            Log.d(TAG, "start NAT port mapping timeout measurement on "
+                    + localProfile.getUriString());
+
+            mIntervalMeasurementProcess =
+                    new IntervalMeasurementProcess(localProfile, maxInterval);
+            mIntervalMeasurementProcess.start();
+        }
+    }
+
+    private void restartPortMappingLifetimeMeasurement(
+            SipProfile localProfile, int maxInterval) {
+        stopPortMappingMeasurement();
+        mKeepAliveInterval = -1;
+        startPortMappingLifetimeMeasurement(localProfile, maxInterval);
     }
 
     private synchronized void addPendingSession(ISipSession session) {
@@ -500,6 +522,33 @@
         return false;
     }
 
+    private synchronized void onKeepAliveIntervalChanged() {
+        for (SipSessionGroupExt group : mSipGroups.values()) {
+            group.onKeepAliveIntervalChanged();
+        }
+    }
+
+    private int getKeepAliveInterval() {
+        return (mKeepAliveInterval < 0)
+                ? DEFAULT_KEEPALIVE_INTERVAL
+                : mKeepAliveInterval;
+    }
+
+    private boolean isBehindNAT(String address) {
+        try {
+            byte[] d = InetAddress.getByName(address).getAddress();
+            if ((d[0] == 10) ||
+                    (((0x000000FF & ((int)d[0])) == 172) &&
+                    ((0x000000F0 & ((int)d[1])) == 16)) ||
+                    (((0x000000FF & ((int)d[0])) == 192) &&
+                    ((0x000000FF & ((int)d[1])) == 168))) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            Log.e(TAG, "isBehindAT()" + address, e);
+        }
+        return false;
+    }
 
     private class SipSessionGroupExt extends SipSessionAdapter {
         private SipSessionGroup mSipGroup;
@@ -527,6 +576,16 @@
             return mSipGroup.containsSession(callId);
         }
 
+        public void onKeepAliveIntervalChanged() {
+            mAutoRegistration.onKeepAliveIntervalChanged();
+        }
+
+        // TODO: remove this method once SipWakeupTimer can better handle variety
+        // of timeout values
+        void setWakeupTimer(SipWakeupTimer timer) {
+            mSipGroup.setWakeupTimer(timer);
+        }
+
         // network connectivity is tricky because network can be disconnected
         // at any instant so need to deal with exceptions carefully even when
         // you think you are connected
@@ -534,7 +593,7 @@
                 SipProfile localProfile, String password) throws SipException {
             try {
                 return new SipSessionGroup(localIp, localProfile, password,
-                        mMyWakeLock);
+                        mTimer, mMyWakeLock);
             } catch (IOException e) {
                 // network disconnected
                 Log.w(TAG, "createSipSessionGroup(): network disconnected?");
@@ -697,158 +756,135 @@
         }
     }
 
-    private class IntervalMeasurementProcess extends SipSessionAdapter
-            implements Runnable {
-        private static final String TAG = "\\INTERVAL/";
-        private static final int MAX_INTERVAL = 120; // seconds
-        private static final int MIN_INTERVAL = SHORT_EXPIRY_TIME;
-        private static final int PASS_THRESHOLD = 6;
+    private class IntervalMeasurementProcess implements
+            SipSessionGroup.KeepAliveProcessCallback {
+        private static final String TAG = "SipKeepAliveInterval";
+        private static final int MAX_INTERVAL = 120; // in seconds
+        private static final int MIN_INTERVAL = 10; // in seconds
+        private static final int PASS_THRESHOLD = 10;
+        private static final int MAX_RETRY_COUNT = 5;
         private SipSessionGroupExt mGroup;
         private SipSessionGroup.SipSessionImpl mSession;
         private boolean mRunning;
-        private int mMinInterval = 10;
-        private int mMaxInterval = MAX_INTERVAL;
-        private int mInterval = MAX_INTERVAL / 2;
-        private int mPassCounter = 0;
-        private SipWakeupTimer mTimer = new SipWakeupTimer(mContext, mExecutor);
-        // TODO: fix SipWakeupTimer so that we only use one instance of the timer
+        private int mMinInterval = 10; // in seconds
+        private int mMaxInterval;
+        private int mInterval;
+        private int mPassCount = 0;
+        private int mErrorCount = 0;
 
-        public IntervalMeasurementProcess(SipSessionGroup group) {
+        public IntervalMeasurementProcess(SipProfile localProfile, int maxInterval) {
+            mMaxInterval = (maxInterval < 0) ? MAX_INTERVAL : maxInterval;
+            mInterval = (mMaxInterval + mMinInterval) / 2;
+
+            // Don't start measurement if the interval is too small
+            if (mInterval < MIN_INTERVAL) {
+                Log.w(TAG, "interval is too small; measurement aborted; "
+                        + "maxInterval=" + mMaxInterval);
+                return;
+            }
+
             try {
-                mGroup =  new SipSessionGroupExt(
-                        group.getLocalProfile(), null, null);
+                mGroup =  new SipSessionGroupExt(localProfile, null, null);
+                // TODO: remove this line once SipWakeupTimer can better handle
+                // variety of timeout values
+                mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor));
                 mSession = (SipSessionGroup.SipSessionImpl)
-                        mGroup.createSession(this);
+                        mGroup.createSession(null);
             } catch (Exception e) {
                 Log.w(TAG, "start interval measurement error: " + e);
             }
         }
 
         public void start() {
-            if (mRunning) return;
-            mRunning = true;
-            mTimer.set(mInterval * 1000, this);
-            if (DEBUGV) Log.v(TAG, "start interval measurement");
-            run();
+            synchronized (SipService.this) {
+                try {
+                    mSession.startKeepAliveProcess(mInterval, this);
+                } catch (SipException e) {
+                    Log.e(TAG, "start()", e);
+                }
+            }
         }
 
         public void stop() {
-            mRunning = false;
-            mTimer.cancel(this);
+            synchronized (SipService.this) {
+                mSession.stopKeepAliveProcess();
+            }
         }
 
         private void restart() {
-            mTimer.cancel(this);
-            mTimer.set(mInterval * 1000, this);
-        }
-
-        private void calculateNewInterval() {
-            if (!mSession.isReRegisterRequired()) {
-                if (++mPassCounter != PASS_THRESHOLD) return;
-                // update the interval, since the current interval is good to
-                // keep the port mapping.
-                mKeepAliveInterval = mMinInterval = mInterval;
-            } else {
-                // Since the rport is changed, shorten the interval.
-                mSession.clearReRegisterRequired();
-                mMaxInterval = mInterval;
-            }
-            if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) {
-                // update mKeepAliveInterval and stop measurement.
-                stop();
-                mKeepAliveInterval = mMinInterval;
-                if (DEBUGV) Log.v(TAG, "measured interval: " + mKeepAliveInterval);
-            } else {
-                // calculate the new interval and continue.
-                mInterval = (mMaxInterval + mMinInterval) / 2;
-                mPassCounter = 0;
-                if (DEBUGV) {
-                    Log.v(TAG, " current interval: " + mKeepAliveInterval
-                            + "test new interval: " + mInterval);
-                }
-                restart();
-            }
-        }
-
-        public void run() {
             synchronized (SipService.this) {
-                if (!mRunning) return;
                 try {
-                    mSession.sendKeepAlive();
-                    calculateNewInterval();
-                } catch (Throwable t) {
+                    mSession.stopKeepAliveProcess();
+                    mSession.startKeepAliveProcess(mInterval, this);
+                } catch (SipException e) {
+                    Log.e(TAG, "restart()", e);
+                }
+            }
+        }
+
+        // SipSessionGroup.KeepAliveProcessCallback
+        @Override
+        public void onResponse(boolean portChanged) {
+            synchronized (SipService.this) {
+                mErrorCount = 0;
+
+                if (!portChanged) {
+                    if (++mPassCount != PASS_THRESHOLD) return;
+                    // update the interval, since the current interval is good to
+                    // keep the port mapping.
+                    mKeepAliveInterval = mMinInterval = mInterval;
+                    if (DEBUG) {
+                        Log.d(TAG, "measured good keepalive interval: "
+                                + mKeepAliveInterval);
+                    }
+                    onKeepAliveIntervalChanged();
+                } else {
+                    // Since the rport is changed, shorten the interval.
+                    mMaxInterval = mInterval;
+                }
+                if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) {
+                    // update mKeepAliveInterval and stop measurement.
                     stop();
-                    Log.w(TAG, "interval measurement error: " + t);
+                    mKeepAliveInterval = mMinInterval;
+                    if (DEBUG) {
+                        Log.d(TAG, "measured keepalive interval: "
+                                + mKeepAliveInterval);
+                    }
+                } else {
+                    // calculate the new interval and continue.
+                    mInterval = (mMaxInterval + mMinInterval) / 2;
+                    mPassCount = 0;
+                    if (DEBUG) {
+                        Log.d(TAG, "current interval: " + mKeepAliveInterval
+                                + ", test new interval: " + mInterval);
+                    }
+                    restart();
                 }
             }
         }
-    }
 
-    // KeepAliveProcess is controlled by AutoRegistrationProcess.
-    // All methods will be invoked in sync with SipService.this.
-    private class KeepAliveProcess implements Runnable {
-        private static final String TAG = "\\KEEPALIVE/";
-        private static final int INTERVAL = 10;
-        private SipSessionGroup.SipSessionImpl mSession;
-        private boolean mRunning = false;
-        private int mInterval = INTERVAL;
-
-        public KeepAliveProcess(SipSessionGroup.SipSessionImpl session) {
-            mSession = session;
-        }
-
-        public void start() {
-            if (mRunning) return;
-            mRunning = true;
-            mTimer.set(INTERVAL * 1000, this);
-        }
-
-        private void restart(int duration) {
-            if (DEBUG) Log.d(TAG, "Refresh NAT port mapping " + duration + "s later.");
-            mTimer.cancel(this);
-            mTimer.set(duration * 1000, this);
-        }
-
-        // timeout handler
-        public void run() {
+        // SipSessionGroup.KeepAliveProcessCallback
+        @Override
+        public void onError(int errorCode, String description) {
             synchronized (SipService.this) {
-                if (!mRunning) return;
-
-                if (DEBUGV) Log.v(TAG, "~~~ keepalive: "
-                        + mSession.getLocalProfile().getUriString());
-                SipSessionGroup.SipSessionImpl session = mSession.duplicate();
-                try {
-                    session.sendKeepAlive();
-                    if (session.isReRegisterRequired()) {
-                        // Acquire wake lock for the registration process. The
-                        // lock will be released when registration is complete.
-                        mMyWakeLock.acquire(mSession);
-                        mSession.register(EXPIRY_TIME);
-                    }
-                    if (mKeepAliveInterval > mInterval) {
-                        mInterval = mKeepAliveInterval;
-                        restart(mInterval);
-                    }
-                } catch (Throwable t) {
-                    Log.w(TAG, "keepalive error: " + t);
+                Log.w(TAG, "interval measurement error: " + description);
+                if (++mErrorCount < MAX_RETRY_COUNT) {
+                    Log.w(TAG, "  retry count = " + mErrorCount);
+                    mPassCount = 0;
+                    restart();
+                } else {
+                    Log.w(TAG, "  max retry count reached; measurement aborted");
                 }
             }
         }
-
-        public void stop() {
-            if (DEBUGV && (mSession != null)) Log.v(TAG, "stop keepalive:"
-                    + mSession.getLocalProfile().getUriString());
-            mRunning = false;
-            mSession = null;
-            mTimer.cancel(this);
-        }
     }
 
     private class AutoRegistrationProcess extends SipSessionAdapter
-            implements Runnable {
+            implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
+        private String TAG = "SipAudoReg";
         private SipSessionGroup.SipSessionImpl mSession;
+        private SipSessionGroup.SipSessionImpl mKeepAliveSession;
         private SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
-        private KeepAliveProcess mKeepAliveProcess;
         private int mBackoff = 1;
         private boolean mRegistered;
         private long mExpiryTime;
@@ -869,27 +905,51 @@
                 // return right away if no active network connection.
                 if (mSession == null) return;
 
-                synchronized (SipService.this) {
-                    if (isBehindNAT(mLocalIp)
-                            && (mIntervalMeasurementProcess == null)
-                            && (mKeepAliveInterval == -1)) {
-                        // Start keep-alive interval measurement, here we allow
-                        // the first profile only as the target service provider
-                        // to measure the life time of NAT port mapping.
-                        startPortMappingLifetimeMeasurement(group);
-                    }
-                }
-
                 // start unregistration to clear up old registration at server
                 // TODO: when rfc5626 is deployed, use reg-id and sip.instance
                 // in registration to avoid adding duplicate entries to server
                 mMyWakeLock.acquire(mSession);
                 mSession.unregister();
-                if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess for "
-                        + mSession.getLocalProfile().getUriString());
+                if (DEBUG) TAG = mSession.getLocalProfile().getUriString();
+                if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess");
             }
         }
 
+        // SipSessionGroup.KeepAliveProcessCallback
+        @Override
+        public void onResponse(boolean portChanged) {
+            synchronized (SipService.this) {
+                if (portChanged) {
+                    restartPortMappingLifetimeMeasurement(
+                            mSession.getLocalProfile(), getKeepAliveInterval());
+                } else {
+                    // Start keep-alive interval measurement on the first
+                    // successfully kept-alive SipSessionGroup
+                    startPortMappingLifetimeMeasurement(
+                            mSession.getLocalProfile());
+                }
+
+                if (!mRunning || !portChanged) return;
+
+                // The keep alive process is stopped when port is changed;
+                // Nullify the session so that the process can be restarted
+                // again when the re-registration is done
+                mKeepAliveSession = null;
+
+                // Acquire wake lock for the registration process. The
+                // lock will be released when registration is complete.
+                mMyWakeLock.acquire(mSession);
+                mSession.register(EXPIRY_TIME);
+            }
+        }
+
+        // SipSessionGroup.KeepAliveProcessCallback
+        @Override
+        public void onError(int errorCode, String description) {
+            Log.e(TAG, "keepalive error: " + description);
+            onResponse(true); // re-register immediately
+        }
+
         public void stop() {
             if (!mRunning) return;
             mRunning = false;
@@ -900,15 +960,30 @@
             }
 
             mTimer.cancel(this);
-            if (mKeepAliveProcess != null) {
-                mKeepAliveProcess.stop();
-                mKeepAliveProcess = null;
+            if (mKeepAliveSession != null) {
+                mKeepAliveSession.stopKeepAliveProcess();
+                mKeepAliveSession = null;
             }
 
             mRegistered = false;
             setListener(mProxy.getListener());
         }
 
+        public void onKeepAliveIntervalChanged() {
+            if (mKeepAliveSession != null) {
+                int newInterval = getKeepAliveInterval();
+                if (DEBUGV) {
+                    Log.v(TAG, "restart keepalive w interval=" + newInterval);
+                }
+                mKeepAliveSession.stopKeepAliveProcess();
+                try {
+                    mKeepAliveSession.startKeepAliveProcess(newInterval, this);
+                } catch (SipException e) {
+                    Log.e(TAG, "onKeepAliveIntervalChanged()", e);
+                }
+            }
+        }
+
         public void setListener(ISipSessionListener listener) {
             synchronized (SipService.this) {
                 mProxy.setListener(listener);
@@ -955,13 +1030,14 @@
         }
 
         // timeout handler: re-register
+        @Override
         public void run() {
             synchronized (SipService.this) {
                 if (!mRunning) return;
 
                 mErrorCode = SipErrorCode.NO_ERROR;
                 mErrorMessage = null;
-                if (DEBUG) Log.d(TAG, "~~~ registering");
+                if (DEBUG) Log.d(TAG, "registering");
                 if (mConnected) {
                     mMyWakeLock.acquire(mSession);
                     mSession.register(EXPIRY_TIME);
@@ -969,22 +1045,6 @@
             }
         }
 
-        private boolean isBehindNAT(String address) {
-            try {
-                byte[] d = InetAddress.getByName(address).getAddress();
-                if ((d[0] == 10) ||
-                        (((0x000000FF & ((int)d[0])) == 172) &&
-                        ((0x000000F0 & ((int)d[1])) == 16)) ||
-                        (((0x000000FF & ((int)d[0])) == 192) &&
-                        ((0x000000FF & ((int)d[1])) == 168))) {
-                    return true;
-                }
-            } catch (UnknownHostException e) {
-                Log.e(TAG, "isBehindAT()" + address, e);
-            }
-            return false;
-        }
-
         private void restart(int duration) {
             if (DEBUG) Log.d(TAG, "Refresh registration " + duration + "s later.");
             mTimer.cancel(this);
@@ -1030,7 +1090,6 @@
                 mProxy.onRegistrationDone(session, duration);
 
                 if (duration > 0) {
-                    mSession.clearReRegisterRequired();
                     mExpiryTime = SystemClock.elapsedRealtime()
                             + (duration * 1000);
 
@@ -1043,13 +1102,17 @@
                         }
                         restart(duration);
 
-                        if (isBehindNAT(mLocalIp) ||
-                                mSession.getLocalProfile().getSendKeepAlive()) {
-                            if (mKeepAliveProcess == null) {
-                                mKeepAliveProcess =
-                                        new KeepAliveProcess(mSession);
+                        SipProfile localProfile = mSession.getLocalProfile();
+                        if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp)
+                                || localProfile.getSendKeepAlive())) {
+                            mKeepAliveSession = mSession.duplicate();
+                            Log.d(TAG, "start keepalive");
+                            try {
+                                mKeepAliveSession.startKeepAliveProcess(
+                                        getKeepAliveInterval(), this);
+                            } catch (SipException e) {
+                                Log.e(TAG, "AutoRegistrationProcess", e);
                             }
-                            mKeepAliveProcess.start();
                         }
                     }
                     mMyWakeLock.release(session);
@@ -1103,10 +1166,6 @@
         private void restartLater() {
             mRegistered = false;
             restart(backoffDuration());
-            if (mKeepAliveProcess != null) {
-                mKeepAliveProcess.stop();
-                mKeepAliveProcess = null;
-            }
         }
     }
 
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 4837eb9..047eb8d 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -21,6 +21,8 @@
 import gov.nist.javax.sip.header.SIPHeaderNames;
 import gov.nist.javax.sip.header.ProxyAuthenticate;
 import gov.nist.javax.sip.header.WWWAuthenticate;
+import gov.nist.javax.sip.header.extensions.ReferredByHeader;
+import gov.nist.javax.sip.header.extensions.ReplacesHeader;
 import gov.nist.javax.sip.message.SIPMessage;
 
 import android.net.sip.ISipSession;
@@ -28,6 +30,7 @@
 import android.net.sip.SipErrorCode;
 import android.net.sip.SipProfile;
 import android.net.sip.SipSession;
+import android.net.sip.SipSessionAdapter;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -89,6 +92,8 @@
     private static final String THREAD_POOL_SIZE = "1";
     private static final int EXPIRY_TIME = 3600; // in seconds
     private static final int CANCEL_CALL_TIMER = 3; // in seconds
+    private static final int KEEPALIVE_TIMEOUT = 3; // in seconds
+    private static final int INCALL_KEEPALIVE_INTERVAL = 10; // in seconds
     private static final long WAKE_LOCK_HOLDING_TIME = 500; // in milliseconds
 
     private static final EventObject DEREGISTER = new EventObject("Deregister");
@@ -107,25 +112,38 @@
     private SipSessionImpl mCallReceiverSession;
     private String mLocalIp;
 
+    private SipWakeupTimer mWakeupTimer;
     private SipWakeLock mWakeLock;
 
     // call-id-to-SipSession map
     private Map<String, SipSessionImpl> mSessionMap =
             new HashMap<String, SipSessionImpl>();
 
+    // external address observed from any response
+    private String mExternalIp;
+    private int mExternalPort;
+
     /**
      * @param myself the local profile with password crossed out
      * @param password the password of the profile
      * @throws IOException if cannot assign requested address
      */
     public SipSessionGroup(String localIp, SipProfile myself, String password,
-            SipWakeLock wakeLock) throws SipException, IOException {
+            SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException,
+            IOException {
         mLocalProfile = myself;
         mPassword = password;
+        mWakeupTimer = timer;
         mWakeLock = wakeLock;
         reset(localIp);
     }
 
+    // TODO: remove this method once SipWakeupTimer can better handle variety
+    // of timeout values
+    void setWakeupTimer(SipWakeupTimer timer) {
+        mWakeupTimer = timer;
+    }
+
     synchronized void reset(String localIp) throws SipException, IOException {
         mLocalIp = localIp;
         if (localIp == null) return;
@@ -161,6 +179,8 @@
 
         mCallReceiverSession = null;
         mSessionMap.clear();
+
+        resetExternalAddress();
     }
 
     synchronized void onConnectivityChanged() {
@@ -176,6 +196,12 @@
         }
     }
 
+    synchronized void resetExternalAddress() {
+        Log.d(TAG, " reset external addr on " + mSipStack);
+        mExternalIp = null;
+        mExternalPort = 0;
+    }
+
     public SipProfile getLocalProfile() {
         return mLocalProfile;
     }
@@ -349,29 +375,105 @@
         return null;
     }
 
+    private void extractExternalAddress(ResponseEvent evt) {
+        Response response = evt.getResponse();
+        ViaHeader viaHeader = (ViaHeader)(response.getHeader(
+                SIPHeaderNames.VIA));
+        if (viaHeader == null) return;
+        int rport = viaHeader.getRPort();
+        String externalIp = viaHeader.getReceived();
+        if ((rport > 0) && (externalIp != null)) {
+            mExternalIp = externalIp;
+            mExternalPort = rport;
+            Log.d(TAG, " got external addr " + externalIp + ":" + rport
+                    + " on " + mSipStack);
+        }
+    }
+
     private class SipSessionCallReceiverImpl extends SipSessionImpl {
         public SipSessionCallReceiverImpl(ISipSessionListener listener) {
             super(listener);
         }
 
+        private SipSessionImpl createNewSession(RequestEvent event,
+                ISipSessionListener listener, ServerTransaction transaction)
+                throws SipException {
+            SipSessionImpl newSession = new SipSessionImpl(listener);
+            newSession.mServerTransaction = transaction;
+            newSession.mState = SipSession.State.INCOMING_CALL;
+            newSession.mDialog = newSession.mServerTransaction.getDialog();
+            newSession.mInviteReceived = event;
+            newSession.mPeerProfile = createPeerProfile(event.getRequest());
+            newSession.mPeerSessionDescription =
+                    extractContent(event.getRequest());
+            return newSession;
+        }
+
+        private int processInviteWithReplaces(RequestEvent event,
+                ReplacesHeader replaces) {
+            String callId = replaces.getCallId();
+            SipSessionImpl session = mSessionMap.get(callId);
+            if (session == null) {
+                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+            }
+
+            Dialog dialog = session.mDialog;
+            if (dialog == null) return Response.DECLINE;
+
+            if (!dialog.getLocalTag().equals(replaces.getToTag()) ||
+                    !dialog.getRemoteTag().equals(replaces.getFromTag())) {
+                // No match is found, returns 481.
+                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+            }
+
+            ReferredByHeader referredBy = (ReferredByHeader) event.getRequest()
+                    .getHeader(ReferredByHeader.NAME);
+            if ((referredBy == null) ||
+                    !dialog.getRemoteParty().equals(referredBy.getAddress())) {
+                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+            }
+            return Response.OK;
+        }
+
+        private void processNewInviteRequest(RequestEvent event)
+                throws SipException {
+            ReplacesHeader replaces = (ReplacesHeader) event.getRequest()
+                    .getHeader(ReplacesHeader.NAME);
+            SipSessionImpl newSession = null;
+            if (replaces != null) {
+                int response = processInviteWithReplaces(event, replaces);
+                if (DEBUG) {
+                    Log.v(TAG, "ReplacesHeader: " + replaces
+                            + " response=" + response);
+                }
+                if (response == Response.OK) {
+                    SipSessionImpl replacedSession =
+                            mSessionMap.get(replaces.getCallId());
+                    // got INVITE w/ replaces request.
+                    newSession = createNewSession(event,
+                            replacedSession.mProxy.getListener(),
+                            mSipHelper.getServerTransaction(event));
+                    newSession.mProxy.onCallTransferring(newSession,
+                            newSession.mPeerSessionDescription);
+                } else {
+                    mSipHelper.sendResponse(event, response);
+                }
+            } else {
+                // New Incoming call.
+                newSession = createNewSession(event, mProxy,
+                        mSipHelper.sendRinging(event, generateTag()));
+                mProxy.onRinging(newSession, newSession.mPeerProfile,
+                        newSession.mPeerSessionDescription);
+            }
+            if (newSession != null) addSipSession(newSession);
+        }
+
         public boolean process(EventObject evt) throws SipException {
             if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~   " + this + ": "
                     + SipSession.State.toString(mState) + ": processing "
                     + log(evt));
             if (isRequestEvent(Request.INVITE, evt)) {
-                RequestEvent event = (RequestEvent) evt;
-                SipSessionImpl newSession = new SipSessionImpl(mProxy);
-                newSession.mState = SipSession.State.INCOMING_CALL;
-                newSession.mServerTransaction = mSipHelper.sendRinging(event,
-                        generateTag());
-                newSession.mDialog = newSession.mServerTransaction.getDialog();
-                newSession.mInviteReceived = event;
-                newSession.mPeerProfile = createPeerProfile(event.getRequest());
-                newSession.mPeerSessionDescription =
-                        extractContent(event.getRequest());
-                addSipSession(newSession);
-                mProxy.onRinging(newSession, newSession.mPeerProfile,
-                        newSession.mPeerSessionDescription);
+                processNewInviteRequest((RequestEvent) evt);
                 return true;
             } else if (isRequestEvent(Request.OPTIONS, evt)) {
                 mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
@@ -382,6 +484,12 @@
         }
     }
 
+    static interface KeepAliveProcessCallback {
+        /** Invoked when the response of keeping alive comes back. */
+        void onResponse(boolean portChanged);
+        void onError(int errorCode, String description);
+    }
+
     class SipSessionImpl extends ISipSession.Stub {
         SipProfile mPeerProfile;
         SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
@@ -392,12 +500,12 @@
         ClientTransaction mClientTransaction;
         String mPeerSessionDescription;
         boolean mInCall;
-        SessionTimer mTimer;
+        SessionTimer mSessionTimer;
         int mAuthenticationRetryCount;
 
-        // for registration
-        boolean mReRegisterFlag = false;
-        int mRPort = 0;
+        private KeepAliveProcess mKeepAliveProcess;
+
+        private SipSessionImpl mKeepAliveSession;
 
         // lightweight timer
         class SessionTimer {
@@ -467,6 +575,11 @@
             mClientTransaction = null;
 
             cancelSessionTimer();
+
+            if (mKeepAliveSession != null) {
+                mKeepAliveSession.stopKeepAliveProcess();
+                mKeepAliveSession = null;
+            }
         }
 
         public boolean isInCall() {
@@ -512,7 +625,9 @@
                         try {
                             processCommand(command);
                         } catch (Throwable e) {
-                            Log.w(TAG, "command error: " + command, e);
+                            Log.w(TAG, "command error: " + command + ": "
+                                    + mLocalProfile.getUriString(),
+                                    getRootCause(e));
                             onError(e);
                         }
                     }
@@ -553,34 +668,6 @@
             doCommandAsync(DEREGISTER);
         }
 
-        public boolean isReRegisterRequired() {
-            return mReRegisterFlag;
-        }
-
-        public void clearReRegisterRequired() {
-            mReRegisterFlag = false;
-        }
-
-        public void sendKeepAlive() {
-            mState = SipSession.State.PINGING;
-            try {
-                processCommand(new OptionsCommand());
-                for (int i = 0; i < 15; i++) {
-                    if (SipSession.State.PINGING != mState) break;
-                    Thread.sleep(200);
-                }
-                if (SipSession.State.PINGING == mState) {
-                    // FIXME: what to do if server doesn't respond
-                    reset();
-                    if (DEBUG) Log.w(TAG, "no response from ping");
-                }
-            } catch (SipException e) {
-                Log.e(TAG, "sendKeepAlive failed", e);
-            } catch (InterruptedException e) {
-                Log.e(TAG, "sendKeepAlive interrupted", e);
-            }
-        }
-
         private void processCommand(EventObject command) throws SipException {
             if (isLoggable(command)) Log.d(TAG, "process cmd: " + command);
             if (!process(command)) {
@@ -612,11 +699,17 @@
             synchronized (SipSessionGroup.this) {
                 if (isClosed()) return false;
 
+                if (mKeepAliveProcess != null) {
+                    // event consumed by keepalive process
+                    if (mKeepAliveProcess.process(evt)) return true;
+                }
+
                 Dialog dialog = null;
                 if (evt instanceof RequestEvent) {
                     dialog = ((RequestEvent) evt).getDialog();
                 } else if (evt instanceof ResponseEvent) {
                     dialog = ((ResponseEvent) evt).getDialog();
+                    extractExternalAddress((ResponseEvent) evt);
                 }
                 if (dialog != null) mDialog = dialog;
 
@@ -627,9 +720,6 @@
                 case SipSession.State.DEREGISTERING:
                     processed = registeringToReady(evt);
                     break;
-                case SipSession.State.PINGING:
-                    processed = keepAliveProcess(evt);
-                    break;
                 case SipSession.State.READY_TO_CALL:
                     processed = readyForCall(evt);
                     break;
@@ -754,10 +844,6 @@
                 case SipSession.State.OUTGOING_CALL_CANCELING:
                     onError(SipErrorCode.TIME_OUT, event.toString());
                     break;
-                case SipSession.State.PINGING:
-                    reset();
-                    mReRegisterFlag = true;
-                    break;
 
                 default:
                     Log.d(TAG, "   do nothing");
@@ -778,48 +864,6 @@
             return expires;
         }
 
-        private boolean keepAliveProcess(EventObject evt) throws SipException {
-            if (evt instanceof OptionsCommand) {
-                mClientTransaction = mSipHelper.sendKeepAlive(mLocalProfile,
-                        generateTag());
-                mDialog = mClientTransaction.getDialog();
-                addSipSession(this);
-                return true;
-            } else if (evt instanceof ResponseEvent) {
-                return parseOptionsResult(evt);
-            }
-            return false;
-        }
-
-        private boolean parseOptionsResult(EventObject evt) {
-            if (expectResponse(Request.OPTIONS, evt)) {
-                ResponseEvent event = (ResponseEvent) evt;
-                int rPort = getRPortFromResponse(event.getResponse());
-                if (rPort != -1) {
-                    if (mRPort == 0) mRPort = rPort;
-                    if (mRPort != rPort) {
-                        mReRegisterFlag = true;
-                        if (DEBUG) Log.w(TAG, String.format(
-                                "rport is changed: %d <> %d", mRPort, rPort));
-                        mRPort = rPort;
-                    } else {
-                        if (DEBUG_PING) Log.w(TAG, "rport is the same: " + rPort);
-                    }
-                } else {
-                    if (DEBUG) Log.w(TAG, "peer did not respond rport");
-                }
-                reset();
-                return true;
-            }
-            return false;
-        }
-
-        private int getRPortFromResponse(Response response) {
-            ViaHeader viaHeader = (ViaHeader)(response.getHeader(
-                    SIPHeaderNames.VIA));
-            return (viaHeader == null) ? -1 : viaHeader.getRPort();
-        }
-
         private boolean registeringToReady(EventObject evt)
                 throws SipException {
             if (expectResponse(Request.REGISTER, evt)) {
@@ -968,7 +1012,8 @@
                 mServerTransaction = mSipHelper.sendInviteOk(mInviteReceived,
                         mLocalProfile,
                         ((MakeCallCommand) evt).getSessionDescription(),
-                        mServerTransaction);
+                        mServerTransaction,
+                        mExternalIp, mExternalPort);
                 startSessionTimer(((MakeCallCommand) evt).getTimeout());
                 return true;
             } else if (END_CALL == evt) {
@@ -991,7 +1036,13 @@
                 throws SipException {
             // expect ACK, CANCEL request
             if (isRequestEvent(Request.ACK, evt)) {
-                establishCall();
+                String sdp = extractContent(((RequestEvent) evt).getRequest());
+                if (sdp != null) mPeerSessionDescription = sdp;
+                if (mPeerSessionDescription == null) {
+                    onError(SipErrorCode.CLIENT_ERROR, "peer sdp is empty");
+                } else {
+                    establishCall(false);
+                }
                 return true;
             } else if (isRequestEvent(Request.CANCEL, evt)) {
                 // http://tools.ietf.org/html/rfc3261#section-9.2
@@ -1023,7 +1074,7 @@
                 case Response.OK:
                     mSipHelper.sendInviteAck(event, mDialog);
                     mPeerSessionDescription = extractContent(response);
-                    establishCall();
+                    establishCall(true);
                     return true;
                 case Response.UNAUTHORIZED:
                 case Response.PROXY_AUTHENTICATION_REQUIRED:
@@ -1138,15 +1189,15 @@
         // timeout in seconds
         private void startSessionTimer(int timeout) {
             if (timeout > 0) {
-                mTimer = new SessionTimer();
-                mTimer.start(timeout);
+                mSessionTimer = new SessionTimer();
+                mSessionTimer.start(timeout);
             }
         }
 
         private void cancelSessionTimer() {
-            if (mTimer != null) {
-                mTimer.cancel();
-                mTimer = null;
+            if (mSessionTimer != null) {
+                mSessionTimer.cancel();
+                mSessionTimer = null;
             }
         }
 
@@ -1155,10 +1206,26 @@
                     response.getStatusCode());
         }
 
-        private void establishCall() {
+        private void enableKeepAlive() {
+            if (mKeepAliveSession != null) {
+                mKeepAliveSession.stopKeepAliveProcess();
+            } else {
+                mKeepAliveSession = duplicate();
+            }
+            try {
+                mKeepAliveSession.startKeepAliveProcess(
+                        INCALL_KEEPALIVE_INTERVAL, mPeerProfile, null);
+            } catch (SipException e) {
+                Log.w(TAG, "keepalive cannot be enabled; ignored", e);
+                mKeepAliveSession.stopKeepAliveProcess();
+            }
+        }
+
+        private void establishCall(boolean enableKeepAlive) {
             mState = SipSession.State.IN_CALL;
             mInCall = true;
             cancelSessionTimer();
+            if (enableKeepAlive) enableKeepAlive();
             mProxy.onCallEstablished(this, mPeerSessionDescription);
         }
 
@@ -1272,6 +1339,174 @@
             onRegistrationFailed(getErrorCode(statusCode),
                     createErrorMessage(response));
         }
+
+        // Notes: SipSessionListener will be replaced by the keepalive process
+        // @param interval in seconds
+        public void startKeepAliveProcess(int interval,
+                KeepAliveProcessCallback callback) throws SipException {
+            synchronized (SipSessionGroup.this) {
+                startKeepAliveProcess(interval, mLocalProfile, callback);
+            }
+        }
+
+        // Notes: SipSessionListener will be replaced by the keepalive process
+        // @param interval in seconds
+        public void startKeepAliveProcess(int interval, SipProfile peerProfile,
+                KeepAliveProcessCallback callback) throws SipException {
+            synchronized (SipSessionGroup.this) {
+                if (mKeepAliveProcess != null) {
+                    throw new SipException("Cannot create more than one "
+                            + "keepalive process in a SipSession");
+                }
+                mPeerProfile = peerProfile;
+                mKeepAliveProcess = new KeepAliveProcess();
+                mProxy.setListener(mKeepAliveProcess);
+                mKeepAliveProcess.start(interval, callback);
+            }
+        }
+
+        public void stopKeepAliveProcess() {
+            synchronized (SipSessionGroup.this) {
+                if (mKeepAliveProcess != null) {
+                    mKeepAliveProcess.stop();
+                    mKeepAliveProcess = null;
+                }
+            }
+        }
+
+        class KeepAliveProcess extends SipSessionAdapter implements Runnable {
+            private static final String TAG = "SipKeepAlive";
+            private boolean mRunning = false;
+            private KeepAliveProcessCallback mCallback;
+
+            private boolean mPortChanged = false;
+            private int mRPort = 0;
+            private int mInterval; // just for debugging
+
+            // @param interval in seconds
+            void start(int interval, KeepAliveProcessCallback callback) {
+                if (mRunning) return;
+                mRunning = true;
+                mInterval = interval;
+                mCallback = new KeepAliveProcessCallbackProxy(callback);
+                mWakeupTimer.set(interval * 1000, this);
+                if (DEBUG) {
+                    Log.d(TAG, "start keepalive:"
+                            + mLocalProfile.getUriString());
+                }
+
+                // No need to run the first time in a separate thread for now
+                run();
+            }
+
+            // return true if the event is consumed
+            boolean process(EventObject evt) throws SipException {
+                if (mRunning && (mState == SipSession.State.PINGING)) {
+                    if (evt instanceof ResponseEvent) {
+                        if (parseOptionsResult(evt)) {
+                            if (mPortChanged) {
+                                resetExternalAddress();
+                                stop();
+                            } else {
+                                cancelSessionTimer();
+                                removeSipSession(SipSessionImpl.this);
+                            }
+                            mCallback.onResponse(mPortChanged);
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            }
+
+            // SipSessionAdapter
+            // To react to the session timeout event and network error.
+            @Override
+            public void onError(ISipSession session, int errorCode, String message) {
+                stop();
+                mCallback.onError(errorCode, message);
+            }
+
+            // SipWakeupTimer timeout handler
+            // To send out keepalive message.
+            @Override
+            public void run() {
+                synchronized (SipSessionGroup.this) {
+                    if (!mRunning) return;
+
+                    if (DEBUG_PING) {
+                        String peerUri = (mPeerProfile == null)
+                                ? "null"
+                                : mPeerProfile.getUriString();
+                        Log.d(TAG, "keepalive: " + mLocalProfile.getUriString()
+                                + " --> " + peerUri + ", interval=" + mInterval);
+                    }
+                    try {
+                        sendKeepAlive();
+                    } catch (Throwable t) {
+                        Log.w(TAG, "keepalive error: " + ": "
+                                + mLocalProfile.getUriString(), getRootCause(t));
+                        // It's possible that the keepalive process is being stopped
+                        // during session.sendKeepAlive() so need to check mRunning
+                        // again here.
+                        if (mRunning) SipSessionImpl.this.onError(t);
+                    }
+                }
+            }
+
+            void stop() {
+                synchronized (SipSessionGroup.this) {
+                    if (DEBUG) {
+                        Log.d(TAG, "stop keepalive:" + mLocalProfile.getUriString()
+                                + ",RPort=" + mRPort);
+                    }
+                    mRunning = false;
+                    mWakeupTimer.cancel(this);
+                    reset();
+                }
+            }
+
+            private void sendKeepAlive() throws SipException, InterruptedException {
+                synchronized (SipSessionGroup.this) {
+                    mState = SipSession.State.PINGING;
+                    mClientTransaction = mSipHelper.sendOptions(
+                            mLocalProfile, mPeerProfile, generateTag());
+                    mDialog = mClientTransaction.getDialog();
+                    addSipSession(SipSessionImpl.this);
+
+                    startSessionTimer(KEEPALIVE_TIMEOUT);
+                    // when timed out, onError() will be called with SipErrorCode.TIME_OUT
+                }
+            }
+
+            private boolean parseOptionsResult(EventObject evt) {
+                if (expectResponse(Request.OPTIONS, evt)) {
+                    ResponseEvent event = (ResponseEvent) evt;
+                    int rPort = getRPortFromResponse(event.getResponse());
+                    if (rPort != -1) {
+                        if (mRPort == 0) mRPort = rPort;
+                        if (mRPort != rPort) {
+                            mPortChanged = true;
+                            if (DEBUG) Log.d(TAG, String.format(
+                                    "rport is changed: %d <> %d", mRPort, rPort));
+                            mRPort = rPort;
+                        } else {
+                            if (DEBUG) Log.d(TAG, "rport is the same: " + rPort);
+                        }
+                    } else {
+                        if (DEBUG) Log.w(TAG, "peer did not respond rport");
+                    }
+                    return true;
+                }
+                return false;
+            }
+
+            private int getRPortFromResponse(Response response) {
+                ViaHeader viaHeader = (ViaHeader)(response.getHeader(
+                        SIPHeaderNames.VIA));
+                return (viaHeader == null) ? -1 : viaHeader.getRPort();
+            }
+        }
     }
 
     /**
@@ -1363,15 +1598,16 @@
         if (!isLoggable(s)) return false;
         if (evt == null) return false;
 
-        if (evt instanceof OptionsCommand) {
-            return DEBUG_PING;
-        } else if (evt instanceof ResponseEvent) {
+        if (evt instanceof ResponseEvent) {
             Response response = ((ResponseEvent) evt).getResponse();
             if (Request.OPTIONS.equals(response.getHeader(CSeqHeader.NAME))) {
                 return DEBUG_PING;
             }
             return DEBUG;
         } else if (evt instanceof RequestEvent) {
+            if (isRequestEvent(Request.OPTIONS, evt)) {
+                return DEBUG_PING;
+            }
             return DEBUG;
         }
         return false;
@@ -1387,12 +1623,6 @@
         }
     }
 
-    private class OptionsCommand extends EventObject {
-        public OptionsCommand() {
-            super(SipSessionGroup.this);
-        }
-    }
-
     private class RegisterCommand extends EventObject {
         private int mDuration;
 
@@ -1434,4 +1664,46 @@
             return mTimeout;
         }
     }
+
+    /** Class to help safely run KeepAliveProcessCallback in a different thread. */
+    static class KeepAliveProcessCallbackProxy implements KeepAliveProcessCallback {
+        private KeepAliveProcessCallback mCallback;
+
+        KeepAliveProcessCallbackProxy(KeepAliveProcessCallback callback) {
+            mCallback = callback;
+        }
+
+        private void proxy(Runnable runnable) {
+            // One thread for each calling back.
+            // Note: Guarantee ordering if the issue becomes important. Currently,
+            // the chance of handling two callback events at a time is none.
+            new Thread(runnable, "SIP-KeepAliveProcessCallbackThread").start();
+        }
+
+        public void onResponse(final boolean portChanged) {
+            if (mCallback == null) return;
+            proxy(new Runnable() {
+                public void run() {
+                    try {
+                        mCallback.onResponse(portChanged);
+                    } catch (Throwable t) {
+                        Log.w(TAG, "onResponse", t);
+                    }
+                }
+            });
+        }
+
+        public void onError(final int errorCode, final String description) {
+            if (mCallback == null) return;
+            proxy(new Runnable() {
+                public void run() {
+                    try {
+                        mCallback.onError(errorCode, description);
+                    } catch (Throwable t) {
+                        Log.w(TAG, "onError", t);
+                    }
+                }
+            });
+        }
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
index f8be0a8..8655a3a 100644
--- a/voip/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -110,6 +110,20 @@
         });
     }
 
+    public void onCallTransferring(final ISipSession newSession,
+            final String sessionDescription) {
+        if (mListener == null) return;
+        proxy(new Runnable() {
+            public void run() {
+                try {
+                    mListener.onCallTransferring(newSession, sessionDescription);
+                } catch (Throwable t) {
+                    handle(t, "onCallTransferring()");
+                }
+            }
+        });
+    }
+
     public void onCallBusy(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
diff --git a/voip/java/com/android/server/sip/SipWakeupTimer.java b/voip/java/com/android/server/sip/SipWakeupTimer.java
index 9cc26b0..76780c0 100644
--- a/voip/java/com/android/server/sip/SipWakeupTimer.java
+++ b/voip/java/com/android/server/sip/SipWakeupTimer.java
@@ -173,7 +173,7 @@
 
         long triggerTime = event.mTriggerTime;
         if (DEBUG_TIMER) {
-            Log.d(TAG, " add event " + event + " scheduled at "
+            Log.d(TAG, " add event " + event + " scheduled on "
                     + showTime(triggerTime) + " at " + showTime(now)
                     + ", #events=" + mEventQueue.size());
             printQueue();
@@ -267,10 +267,10 @@
         if (stopped() || mEventQueue.isEmpty()) return;
 
         for (MyEvent event : mEventQueue) {
-            if (event.mTriggerTime != triggerTime) break;
+            if (event.mTriggerTime != triggerTime) continue;
             if (DEBUG_TIMER) Log.d(TAG, "execute " + event);
 
-            event.mLastTriggerTime = event.mTriggerTime;
+            event.mLastTriggerTime = triggerTime;
             event.mTriggerTime += event.mPeriod;
 
             // run the callback in the handler thread to prevent deadlock
@@ -324,6 +324,8 @@
         }
     }
 
+    // Sort the events by mMaxPeriod so that the first event can be used to
+    // align events with larger periods
     private static class MyEventComparator implements Comparator<MyEvent> {
         public int compare(MyEvent e1, MyEvent e2) {
             if (e1 == e2) return 0;